[clang] 6f59d5d - [CIR] Support vector of bool with padding (#215850)

via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 14 09:24:01 PDT 2026


Author: Amr Hesham
Date: 2026-08-14T18:23:55+02:00
New Revision: 6f59d5df7fc1a15e4e499f3ee3fe2c4e6f973f3b

URL: https://github.com/llvm/llvm-project/commit/6f59d5df7fc1a15e4e499f3ee3fe2c4e6f973f3b
DIFF: https://github.com/llvm/llvm-project/commit/6f59d5df7fc1a15e4e499f3ee3fe2c4e6f973f3b.diff

LOG: [CIR] Support vector of bool with padding (#215850)

Support the vector of bool emit from and to memory with padding

Added: 
    

Modified: 
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
    clang/test/CIR/CodeGen/vector-bool.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 4ae4b7693d982..040af9c9cb9b1 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -199,6 +199,24 @@ lowerCIRVisibilityToLLVMVisibility(cir::VisibilityKind visibilityKind) {
   }
 }
 
+static mlir::Value
+emitBoolVecConversion(mlir::ConversionPatternRewriter &rewriter,
+                      mlir::Value srcVec, unsigned numElementsDst) {
+  auto srcTy = mlir::cast<mlir::VectorType>(srcVec.getType());
+  unsigned numElementsSrc = srcTy.getNumElements();
+  if (numElementsSrc == numElementsDst)
+    return srcVec;
+
+  SmallVector<int32_t, 8> mask(numElementsDst, -1);
+  for (unsigned i : llvm::seq(std::min(numElementsDst, numElementsSrc)))
+    mask[i] = i;
+
+  mlir::Location loc = srcVec.getLoc();
+  auto poison = mlir::LLVM::PoisonOp::create(rewriter, loc, srcVec.getType());
+  return mlir::LLVM::ShuffleVectorOp::create(rewriter, loc, srcVec, poison,
+                                             mask);
+}
+
 /// Emits the value from memory as expected by its users. Should be called when
 /// the memory represetnation of a CIR type is not equal to its scalar
 /// representation.
@@ -216,9 +234,15 @@ static mlir::Value emitFromMemory(mlir::ConversionPatternRewriter &rewriter,
   // 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);
+      auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
+      auto paddedVecTy =
+          cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth());
+      mlir::Type mlirVecTy = converter.convertType(paddedVecTy);
+      // Bitcast iP --> <P x i1>.
+      auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(),
+                                             mlirVecTy, value);
+      // Shuffle <P x i1> --> <N x i1> (N is the actual bit size).
+      return emitBoolVecConversion(rewriter, v, vecTy.getSize());
     }
   }
 
@@ -251,6 +275,7 @@ static mlir::Value emitToMemory(mlir::ConversionPatternRewriter &rewriter,
     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);
+      value = emitBoolVecConversion(rewriter, value, resultTy.getWidth());
       return mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), resultTy,
                                            value);
     }

diff  --git a/clang/test/CIR/CodeGen/vector-bool.cpp b/clang/test/CIR/CodeGen/vector-bool.cpp
index 724d8109b048a..106048fc49517 100644
--- a/clang/test/CIR/CodeGen/vector-bool.cpp
+++ b/clang/test/CIR/CodeGen/vector-bool.cpp
@@ -1,10 +1,12 @@
 // 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: FileCheck --input-file=%t-cir.ll %s -check-prefixes=LLVM,SHARED
 // 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=LLVM
+// RUN: FileCheck --input-file=%t.ll %s -check-prefixes=OGCG,SHARED
 
+typedef bool v4b __attribute__((ext_vector_type(4)));
+typedef bool v5b __attribute__((ext_vector_type(5)));
 typedef bool v8b __attribute__((ext_vector_type(8)));
 
 void vec_bool_without_padding_needed() {
@@ -15,8 +17,8 @@ void vec_bool_without_padding_needed() {
 // 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, {{.*}}align 1
-// LLVM: %[[B_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[A_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[B_ADDR:.*]] = alloca i8, {{.*}}align 1
 
 void vec_bool_load_store_without_padding_needed() {
   v8b a;
@@ -29,12 +31,12 @@ void vec_bool_load_store_without_padding_needed() {
 // 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, {{.*}}align 1
-// LLVM: %[[B_ADDR:.*]] = alloca i8, {{.*}}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
+// SHARED: %[[A_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[B_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[TMP_B:.*]] = load i8, ptr %[[B_ADDR]], align 1
+// SHARED: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// SHARED: %[[TMP_B_I8:.*]] = bitcast <8 x i1> %[[TMP_B_VEC]] to i8
+// SHARED: store i8 %[[TMP_B_I8]], ptr %[[A_ADDR]], align 1
 
 void vec_bool_extract_insert_without_padding_needed() {
   v8b a;
@@ -52,13 +54,87 @@ void vec_bool_extract_insert_without_padding_needed() {
 // CIR: %[[RESULT:.*]] = cir.vec.insert %[[B_ELEM_3]], %[[TMP_A]][%[[CONST_2]] : !s32i] : !cir.vector<8 x !cir.bool>
 // CIR: cir.store {{.*}} %[[RESULT]], %[[A_ADDR]] : !cir.vector<8 x !cir.bool>, !cir.ptr<!cir.vector<8 x !cir.bool>>
 
-// LLVM: %[[A_ADDR:.*]] = alloca i8, {{.*}}align 1
-// LLVM: %[[B_ADDR:.*]] = alloca i8, {{.*}}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: %[[B_ELEM_3:.*]] = extractelement <8 x i1> %[[TMP_B_VEC]], i32 3
-// LLVM: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 1
-// LLVM: %[[TMP_A_VEC:.*]] = bitcast i8 %[[TMP_A]] to <8 x i1>
-// LLVM: %[[RESULT:.*]] = insertelement <8 x i1> %[[TMP_A_VEC]], i1 %[[B_ELEM_3]], i32 2
-// LLVM: %[[RESULT_I8:.*]] = bitcast <8 x i1> %[[RESULT]] to i8
-// LLVM: store i8 %[[RESULT_I8]], ptr %[[A_ADDR]], align 1
+// SHARED: %[[A_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[B_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[TMP_B:.*]] = load i8, ptr %[[B_ADDR]], align 1
+// SHARED: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// SHARED: %[[B_ELEM_3:.*]] = extractelement <8 x i1> %[[TMP_B_VEC]], i32 3
+// SHARED: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 1
+// SHARED: %[[TMP_A_VEC:.*]] = bitcast i8 %[[TMP_A]] to <8 x i1>
+// SHARED: %[[RESULT:.*]] = insertelement <8 x i1> %[[TMP_A_VEC]], i1 %[[B_ELEM_3]], i32 2
+// SHARED: %[[RESULT_I8:.*]] = bitcast <8 x i1> %[[RESULT]] to i8
+// SHARED: store i8 %[[RESULT_I8]], ptr %[[A_ADDR]], align 1
+
+void vec_bool_4_extract_insert_without_padding_needed() {
+  v4b a;
+  v4b b;
+  a[2] = b[3];
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!cir.vector<4 x !cir.bool>>
+// CIR: %1 = cir.alloca "b" {{.*}} : !cir.ptr<!cir.vector<4 x !cir.bool>>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<4 x !cir.bool>>, !cir.vector<4 x !cir.bool>
+// CIR: %[[CONST_3:.*]] = cir.const #cir.int<3> : !s32i
+// CIR: %[[EXTRACT:.*]] = cir.vec.extract %[[TMP_B]][%[[CONST_3]] : !s32i] : !cir.vector<4 x !cir.bool>
+// CIR: %[[CONST_2:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: %[[TMP_A:.*]] = cir.load {{.*}} %[[A_ADDR]] : !cir.ptr<!cir.vector<4 x !cir.bool>>, !cir.vector<4 x !cir.bool>
+// CIR: %[[INSERT:.*]] = cir.vec.insert %[[EXTRACT]], %[[TMP_A]][%[[CONST_2]] : !s32i] : !cir.vector<4 x !cir.bool>
+// CIR: cir.store {{.*}} %[[INSERT]], %[[A_ADDR]] : !cir.vector<4 x !cir.bool>, !cir.ptr<!cir.vector<4 x !cir.bool>>
+
+// SHARED: %[[A_ADDR:.*]] = alloca i8, align 1
+// SHARED: %[[B_ADDR:.*]] = alloca i8, align 1
+// SHARED: %[[TMP_B:.*]] = load i8, ptr %[[B_ADDR]], align 1
+// SHARED: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// SHARED: %[[EXTRACT_VEC:.*]] = shufflevector <8 x i1> %[[TMP_B_VEC]], <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// SHARED: %[[B_ELEM_3:.*]] = extractelement <4 x i1> %[[EXTRACT_VEC]], i32 3
+// SHARED: %[[TMP_A:.*]] = load i8, ptr %[[A_ADDR]], align 1
+// SHARED: %[[TMP_A_VEC:.*]] = bitcast i8 %{{.*}} to <8 x i1>
+
+// LLVM: %[[TMP_A_VEC_4:.*]] = shufflevector <8 x i1> %[[TMP_A_VEC]], <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// LLVM: %[[INSERT:.*]] = insertelement <4 x i1> %[[TMP_A_VEC_4]], i1 %[[B_ELEM_3]], i32 2
+// LLVM: %[[TMP_A_VEC_8:.*]] = shufflevector <4 x i1> %[[INSERT]], <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
+
+// OGCG: %[[TMP_A_VEC_8:.*]] = insertelement <8 x i1> %[[TMP_A_VEC]], i1 %[[B_ELEM_3]], i32 2
+
+// SHARED: %[[RESULT:.*]] = bitcast <8 x i1> %[[TMP_A_VEC_8]] to i8
+// SHARED: store i8 %[[RESULT]], ptr %[[A_ADDR]], align 1
+
+void vec_bool_load_store_with_padding_needed() {
+  v4b a;
+  v4b b;
+  a = b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!cir.vector<4 x !cir.bool>>
+// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!cir.vector<4 x !cir.bool>>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<4 x !cir.bool>>, !cir.vector<4 x !cir.bool>
+// CIR: cir.store {{.*}} %[[TMP_B]], %[[A_ADDR]] : !cir.vector<4 x !cir.bool>, !cir.ptr<!cir.vector<4 x !cir.bool>>
+
+// SHARED: %[[A_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[B_ADDR:.*]] = alloca i8, {{.*}}align 1
+// SHARED: %[[TMP_B:.*]] = load i8, ptr %[[B_ADDR]], align 1
+// SHARED: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// SHARED: %[[EXTRACT_VEC:.*]] = shufflevector <8 x i1> %[[TMP_B_VEC]], <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// SHARED: %[[INSERT_VEC:.*]] = shufflevector <4 x i1> %[[EXTRACT_VEC]], <4 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
+// SHARED: %[[RESULT:.*]] = bitcast <8 x i1> %[[INSERT_VEC]] to i8
+// SHARED: store i8 %[[RESULT]], ptr %[[A_ADDR]], align 1
+
+void vec_bool_5_load_store_with_padding_needed() {
+  v5b a;
+  v5b b;
+  a = b;
+}
+
+// CIR: %[[A_ADDR:.*]] = cir.alloca "a" {{.*}} : !cir.ptr<!cir.vector<5 x !cir.bool>>
+// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!cir.vector<5 x !cir.bool>>
+// CIR: %[[TMP_B:.*]] = cir.load {{.*}} %[[B_ADDR]] : !cir.ptr<!cir.vector<5 x !cir.bool>>, !cir.vector<5 x !cir.bool>
+// CIR: cir.store {{.*}} %[[TMP_B]], %[[A_ADDR]] : !cir.vector<5 x !cir.bool>, !cir.ptr<!cir.vector<5 x !cir.bool>>
+
+// SHARED: %[[A_ADDR:.*]] = alloca i8, align 1
+// SHARED: %[[B_ADDR:.*]] = alloca i8, align 1
+// SHARED: %[[TMP_B:.*]] = load i8, ptr %[[B_ADDR]], align 1
+// SHARED: %[[TMP_B_VEC:.*]] = bitcast i8 %[[TMP_B]] to <8 x i1>
+// SHARED: %[[EXTRACT_VEC:.*]] = shufflevector <8 x i1> %[[TMP_B_VEC]], <8 x i1> poison, <5 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4>
+// SHARED: %[[INSERT_VEC:.*]] = shufflevector <5 x i1> %[[EXTRACT_VEC]], <5 x i1> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 poison, i32 poison, i32 poison>
+// SHARED: %[[RESULT:.*]] = bitcast <8 x i1> %[[INSERT_VEC]] to i8
+// SHARED: store i8 %[[RESULT]], ptr %[[A_ADDR]], align 1


        


More information about the cfe-commits mailing list