[CIR] Support vector of bool with padding - #215850
Conversation
|
@llvm/pr-subscribers-clang @llvm/pr-subscribers-clangir Author: Amr Hesham (AmrDeveloper) ChangesSupport the vector of bool emit from and to memory with padding Full diff: https://github.com/llvm/llvm-project/pull/215850.diff 2 Files Affected:
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index ccdc974ca1b93..0aad68f83e9e4 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, cir::VectorType srcTy,
+ unsigned numElementsDst) {
+ unsigned numElementsSrc = srcTy.getSize();
+ 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, paddedVecTy, vecTy.getSize());
}
}
@@ -251,6 +275,8 @@ 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, vecTy, 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..c777dc95414ab 100644
--- a/clang/test/CIR/CodeGen/vector-bool.cpp
+++ b/clang/test/CIR/CodeGen/vector-bool.cpp
@@ -5,6 +5,7 @@
// 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
+typedef bool v4b __attribute__((ext_vector_type(4)));
typedef bool v8b __attribute__((ext_vector_type(8)));
void vec_bool_without_padding_needed() {
@@ -62,3 +63,23 @@ void vec_bool_extract_insert_without_padding_needed() {
// 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
+
+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>>
+
+// 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: %[[EXTRACT_VEC:.*]] = shufflevector <8 x i1> %[[TMP_B_VEC]], <8 x i1> poison, <4 x i32> <i32 0, i32 1, i32 2, i32 3>
+// LLVM: %[[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>
+// LLVM: %[[RESULT:.*]] = bitcast <8 x i1> %[[INSERT_VEC]] to i8
+// LLVM: store i8 %[[RESULT]], ptr %[[A_ADDR]], align 1
|
bcardosolopes
left a comment
There was a problem hiding this comment.
LGTM: two inline comments, neither blocking.
| emitBoolVecConversion(mlir::ConversionPatternRewriter &rewriter, | ||
| mlir::Value srcVec, cir::VectorType srcTy, | ||
| unsigned numElementsDst) { | ||
| unsigned numElementsSrc = srcTy.getSize(); |
There was a problem hiding this comment.
OG reads the source count off the value instead of taking a type alongside it (CodeGenFunction.cpp:3455, cast<llvm::FixedVectorType>(SrcVec->getType())). Same thing here would drop the parameter and remove any chance of srcTy and srcVec disagreeing about the lane count.
emitFromMemory then only needs paddedVecTy for the bitcast, and the call reads emitBoolVecConversion(rewriter, v, vecTy.getSize()).
| // LLVM: %[[RESULT_I8:.*]] = bitcast <8 x i1> %[[RESULT]] to i8 | ||
| // LLVM: store i8 %[[RESULT_I8]], ptr %[[A_ADDR]], align 1 | ||
|
|
||
| void vec_bool_load_store_with_padding_needed() { |
There was a problem hiding this comment.
bytePadded is max(N, 8), so padding only ever happens below 8 lanes: 1 to 7 is the whole interesting range, and it's covered here for load/store only.
Can you add the v4b companion to vec_bool_extract_insert_without_padding_needed? That's the path where the shuffle has to land on exactly <4 x i1> for the extractelement/insertelement index to mean anything, so it's the more useful of the two. An odd size like ext_vector_type(3) would be a good second data point.
Support the vector of bool emit from and to memory with padding