llvmorg-github-actions[bot] wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Amr Hesham (AmrDeveloper)

<details>
<summary>Changes</summary>

Implement load and store support for a vector of bools 

Issue #<!-- -->161233

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


6 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+55-19) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+15) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+33) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+14) 
- (added) clang/test/CIR/CodeGen/vector-bool.cpp (+22) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 1517de5200734..5ee2ac7b02ea4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -469,20 +469,18 @@ 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)
-      cgm.errorNYI(addr.getPointer().getLoc(),
-                   "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");
+    mlir::Type srcTy = value.getType();
+    if (auto vecTy = dyn_cast<cir::VectorType>(srcTy)) {
+      // TODO(CIR): Use `ABIInfo::getOptimalVectorMemoryType` once it 
upstreamed
+      assert(!cir::MissingFeatures::cirgenABIInfo());
+      if (!clangVecTy->isPackedVectorBoolType(getContext()) &&
+          vecTy.getSize() == 3 && !getLangOpts().PreserveVec3Type)
+        cgm.errorNYI(addr.getPointer().getLoc(),
+                     "emitStoreOfScalar Vec3 & PreserveVec3Type disabled");
+
+      if (addr.getElementType() != srcTy)
+        addr = addr.withElementType(builder, srcTy);
+    }
   }
 
   value = emitToMemory(value, ty);
@@ -709,7 +707,24 @@ mlir::Value CIRGenFunction::emitToMemory(mlir::Value 
value, QualType ty) {
     ty = atomicTy->getValueType();
 
   if (ty->isExtVectorBoolType()) {
-    cgm.errorNYI("emitToMemory: extVectorBoolType");
+    mlir::Type storeTy = convertTypeForLoadStore(ty);
+    if (value.getType() == storeTy)
+      return value;
+
+    const cir::CIRDataLayout dataLayout = cgm.getDataLayout();
+    if (isa<cir::VectorType>(storeTy) &&
+        dataLayout.getTypeSizeInBits(storeTy) >
+            dataLayout.getTypeSizeInBits(value.getType())) {
+      cgm.errorNYI("emitToMemory ExtVectorBoolType store.size > value.size");
+      return {};
+    }
+
+    // Expand to the memory bit width.
+    unsigned memNumElems = cgm.getDataLayout().getTypeSizeInBits(storeTy);
+    // <N x i1> --> <P x i1>.
+    value = emitBoolVecConversion(value, memNumElems);
+    // <P x i1> --> iP.
+    value = builder.createBitcast(value, storeTy);
   }
 
   // Unlike in classic codegen CIR, bools are kept as `cir.bool` and BitInts 
are
@@ -723,7 +738,14 @@ mlir::Value CIRGenFunction::emitFromMemory(mlir::Value 
value, QualType ty) {
     ty = atomicTy->getValueType();
 
   if (ty->isPackedVectorBoolType(getContext())) {
-    cgm.errorNYI("emitFromMemory: PackedVectorBoolType");
+    mlir::Type rawIntTy = value.getType();
+    unsigned widh = cgm.getDataLayout().getTypeSizeInBits(rawIntTy);
+    auto paddingVecTy = cir::VectorType::get(builder.getBoolTy(), widh);
+    auto v = builder.createBitcast(value, paddingVecTy);
+
+    mlir::Type valTy = convertType(ty);
+    unsigned valNumElems = cast<cir::VectorType>(valTy).getSize();
+    return emitBoolVecConversion(v, valNumElems);
   }
 
   return value;
@@ -750,9 +772,23 @@ mlir::Value CIRGenFunction::emitLoadOfScalar(Address addr, 
bool isVolatile,
   mlir::Type eltTy = addr.getElementType();
 
   if (const auto *clangVecTy = ty->getAs<clang::VectorType>()) {
-    if (clangVecTy->isExtVectorBoolType()) {
-      cgm.errorNYI(loc, "emitLoadOfScalar: ExtVectorBoolType");
-      return nullptr;
+    // Boolean vectors use `iN` as storage type.
+    if (clangVecTy->isPackedVectorBoolType(getContext())) {
+      mlir::Type valTy = convertType(ty);
+      unsigned valNumElements = cast<cir::VectorType>(valTy).getSize();
+      // Load the `iP` storage object (P is the padded vector size).
+      mlir::Value rawIntV = builder.createLoad(getLoc(loc), addr, isVolatile);
+      mlir::Type rawIntTy = rawIntV.getType();
+      assert(isa<cir::IntTypeInterface>(rawIntTy) &&
+             "compressed 1N storage for bitvectors");
+      // Bitcast iP --> <P x i1>.
+      auto paddingVecTy = cir::VectorType::get(
+          builder.getBoolTy(),
+          cast<cir::IntTypeInterface>(rawIntTy).getWidth());
+      auto v = builder.createBitcast(getLoc(loc), rawIntV, paddingVecTy);
+      // Shuffle <P x i1> --> <N x i1> (N is the actual bit size).
+      v = emitBoolVecConversion(v, valNumElements);
+      return emitFromMemory(v, ty);
     }
 
     const auto vecTy = cast<cir::VectorType>(eltTy);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index 92568dcc3dfd8..1a3afa45ceeb0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -105,6 +105,10 @@ mlir::Type CIRGenFunction::convertType(QualType t) {
   return cgm.getTypes().convertType(t);
 }
 
+mlir::Type CIRGenFunction::convertTypeForLoadStore(QualType astTy) {
+  return cgm.getTypes().convertTypeForLoadStore(astTy);
+}
+
 mlir::Location CIRGenFunction::getLoc(SourceLocation srcLoc) {
   // Some AST nodes might contain invalid source locations (e.g.
   // CXXDefaultArgExpr), workaround that to still get something out.
@@ -804,6 +808,17 @@ cir::FuncOp CIRGenFunction::generateCode(clang::GlobalDecl 
gd, cir::FuncOp fn,
   return fn;
 }
 
+mlir::Value CIRGenFunction::emitBoolVecConversion(mlir::Value srcVec,
+                                                  unsigned numElementsDst) {
+  auto srcTy = cast<cir::VectorType>(srcVec.getType());
+  unsigned numElementsSrc = srcTy.getSize();
+  if (numElementsSrc == numElementsDst)
+    return srcVec;
+
+  llvm_unreachable("emitBoolVecConversion");
+  return {};
+}
+
 void CIRGenFunction::emitConstructorBody(FunctionArgList &args) {
   assert(!cir::MissingFeatures::sanitizers());
   const auto *ctor = cast<CXXConstructorDecl>(curGD.getDecl());
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index d88f38eefa99a..d36b4ac3bc359 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -271,6 +271,7 @@ class CIRGenFunction : public CIRGenTypeCache {
   mlir::Type convertTypeForMem(QualType t);
 
   mlir::Type convertType(clang::QualType t);
+  mlir::Type convertTypeForLoadStore(QualType astTy);
   mlir::Type convertType(const TypeDecl *t) {
     return convertType(getContext().getTypeDeclType(t));
   }
@@ -1984,6 +1985,9 @@ class CIRGenFunction : public CIRGenTypeCache {
 
   void emitBeginCatch(const CXXCatchStmt *catchStmt, mlir::Value ehToken);
 
+  // Truncate or extend a boolean vector to the requested number of elements.
+  mlir::Value emitBoolVecConversion(mlir::Value srcVec, unsigned 
numElementsDs);
+
   mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s,
                                      cxxTryBodyEmitter &bodyCallback);
   mlir::LogicalResult emitCXXTryStmt(const clang::CXXTryStmt &s);
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index e5af4eec7720f..e4d17eaebb6d9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -689,6 +689,21 @@ mlir::Type CIRGenTypes::convertTypeForMem(clang::QualType 
qualType,
 
   mlir::Type convertedType = convertType(qualType);
 
+  // Check for the boolean vector case.
+  if (qualType->isExtVectorBoolType()) {
+    auto vecTy = cast<cir::VectorType>(convertedType);
+
+    if (astContext.getLangOpts().HLSL) {
+      cgm.errorNYI("convertTypeForMem: ExtVectorBoolType HLSL");
+      return {};
+    }
+
+    // Pad to at least one byte.
+    uint64_t bytePadded = std::max<uint64_t>(vecTy.getSize(), 8);
+    return cir::IntType::get(builder.getContext(), bytePadded,
+                             /*is_signed=*/false);
+  }
+
   assert(!forBitField && "Bit fields NYI");
 
   // If this is a bit-precise integer type in a bitfield representation, map
@@ -699,6 +714,24 @@ mlir::Type CIRGenTypes::convertTypeForMem(clang::QualType 
qualType,
   return convertedType;
 }
 
+mlir::Type CIRGenTypes::convertTypeForLoadStore(clang::QualType t) {
+  if (t->isBitIntType()) {
+    cgm.errorNYI("convertTypeForLoadStore: BitIntType");
+    return {};
+  }
+
+  if (t->isConstantMatrixBoolType()) {
+    cgm.errorNYI("convertTypeForLoadStore: ConstantMatrixBoolType");
+    return {};
+  }
+
+  if (t->isExtVectorBoolType()) {
+    return convertTypeForMem(t);
+  }
+
+  return convertType(t);
+}
+
 /// Return record layout info for the given record decl.
 const CIRGenRecordLayout &
 CIRGenTypes::getCIRGenRecordLayout(const RecordDecl *rd) {
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h 
b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index a7827f76bd5f2..354e67b05bd4a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -145,6 +145,20 @@ class CIRGenTypes {
   // TODO: convert this comment to account for MLIR's equivalence
   mlir::Type convertTypeForMem(clang::QualType, bool forBitField = false);
 
+  /// Given that T is a scalar type, return the IR type that should
+  /// be used for load and store operations.  For example, this might
+  /// be i8 for _Bool or i96 for _BitInt(65).  The store size of the
+  /// load/store type (as reported by LLVM's data layout) is always
+  /// the same as the alloc size of the memory representation type
+  /// returned by ConvertTypeForMem.
+  ///
+  /// As an optimization, if you already know the scalar value type
+  /// for T (as would be returned by ConvertType), you can pass
+  /// it as the second argument so that it does not need to be
+  /// recomputed in common cases where the value type and
+  /// load/store type are the same.
+  mlir::Type convertTypeForLoadStore(QualType t);
+
   /// Get the CIR function type for \arg Info.
   cir::FuncType getFunctionType(const CIRGenFunctionInfo &info);
 
diff --git a/clang/test/CIR/CodeGen/vector-bool.cpp 
b/clang/test/CIR/CodeGen/vector-bool.cpp
new file mode 100644
index 0000000000000..202dbddd344c0
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vector-bool.cpp
@@ -0,0 +1,22 @@
+// 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<!u8i>
+// CIR: %[[B_ADDR:.*]] = cir.alloca "b" {{.*}} : !cir.ptr<!u8i>
+
+// 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

``````````

</details>


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

Reply via email to