Author: Amr Hesham
Date: 2025-04-26T16:11:43+02:00
New Revision: d59163092dfa7ec94391121ffdcb7b9b0e58f3b4

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

LOG: [CIR] Upstream initial support for fixed size VectorType (#136488)

This change adds the initial support for VectorType

Issue #136487

Added: 
    clang/test/CIR/CodeGen/vector-ext.cpp
    clang/test/CIR/CodeGen/vector.cpp
    clang/test/CIR/IR/invalid-vector-zero-size.cir
    clang/test/CIR/IR/invalid-vector.cir
    clang/test/CIR/IR/vector.cir

Modified: 
    clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
    clang/include/clang/CIR/Dialect/IR/CIRTypes.td
    clang/lib/CIR/CodeGen/CIRGenBuilder.h
    clang/lib/CIR/CodeGen/CIRGenTypes.cpp
    clang/lib/CIR/Dialect/IR/CIRDialect.cpp
    clang/lib/CIR/Dialect/IR/CIRTypes.cpp
    clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h 
b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index ef29791ed2783..d58ced6ec8bff 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -90,6 +90,8 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
       return cir::FPAttr::getZero(ty);
     if (auto arrTy = mlir::dyn_cast<cir::ArrayType>(ty))
       return cir::ZeroAttr::get(arrTy);
+    if (auto vecTy = mlir::dyn_cast<cir::VectorType>(ty))
+      return cir::ZeroAttr::get(vecTy);
     if (auto ptrTy = mlir::dyn_cast<cir::PointerType>(ty))
       return getConstNullPtrAttr(ptrTy);
     if (auto recordTy = mlir::dyn_cast<cir::RecordType>(ty))

diff  --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 0a821e152d353..c752bc822f5c0 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -307,6 +307,43 @@ def CIR_ArrayType : CIR_Type<"Array", "array",
   }];
 }
 
+//===----------------------------------------------------------------------===//
+// VectorType (fixed size)
+//===----------------------------------------------------------------------===//
+
+def CIR_VectorType : CIR_Type<"Vector", "vector",
+    [DeclareTypeInterfaceMethods<DataLayoutTypeInterface>]> {
+
+  let summary = "CIR vector type";
+  let description = [{
+   `!cir.vector' represents fixed-size vector types, parameterized
+    by the element type and the number of elements.
+
+    Example:
+
+    ```mlir
+    !cir.vector<!u64i x 2>
+    !cir.vector<!cir.float x 4>
+    ```
+  }];
+
+  let parameters = (ins "mlir::Type":$elementType, "uint64_t":$size);
+
+  let assemblyFormat = [{
+    `<` $size `x` $elementType `>`
+  }];
+
+  let builders = [
+    TypeBuilderWithInferredContext<(ins
+      "mlir::Type":$elementType, "uint64_t":$size
+    ), [{
+        return $_get(elementType.getContext(), elementType, size);
+    }]>,
+  ];
+
+  let genVerifyDecl = 1;
+}
+
 
//===----------------------------------------------------------------------===//
 // FuncType
 
//===----------------------------------------------------------------------===//
@@ -533,8 +570,8 @@ def CIRRecordType : Type<
 
//===----------------------------------------------------------------------===//
 
 def CIR_AnyType : AnyTypeOf<[
-  CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_IntType, CIR_AnyFloat,
-  CIR_PointerType, CIR_FuncType, CIR_RecordType
+  CIR_VoidType, CIR_BoolType, CIR_ArrayType, CIR_VectorType, CIR_IntType,
+  CIR_AnyFloat, CIR_PointerType, CIR_FuncType, CIR_RecordType
 ]>;
 
 #endif // MLIR_CIR_DIALECT_CIR_TYPES

diff  --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h 
b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 7d9988cc52c5a..5f3bf8b416cde 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -83,6 +83,9 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
                   cir::IntType>(ty))
       return true;
 
+    if (const auto vt = mlir::dyn_cast<cir::VectorType>(ty))
+      return isSized(vt.getElementType());
+
     assert(!cir::MissingFeatures::unsizedTypes());
     return false;
   }

diff  --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index b11f8466607f8..de8ea0bd92158 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -399,6 +399,14 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
     break;
   }
 
+  case Type::ExtVector:
+  case Type::Vector: {
+    const VectorType *vec = cast<VectorType>(ty);
+    const mlir::Type elemTy = convertType(vec->getElementType());
+    resultType = cir::VectorType::get(elemTy, vec->getNumElements());
+    break;
+  }
+
   case Type::FunctionNoProto:
   case Type::FunctionProto:
     resultType = convertFunctionTypeInternal(type);

diff  --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 3cd17053a52ba..939802a3af680 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -220,7 +220,7 @@ static LogicalResult checkConstantTypes(mlir::Operation 
*op, mlir::Type opType,
   }
 
   if (isa<cir::ZeroAttr>(attrType)) {
-    if (isa<cir::RecordType, cir::ArrayType>(opType))
+    if (isa<cir::RecordType, cir::ArrayType, cir::VectorType>(opType))
       return success();
     return op->emitOpError("zero expects struct or array type");
   }

diff  --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index c6133b9a20e4f..1574f40a0e74c 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -652,7 +652,7 @@ BoolType::getABIAlignment(const ::mlir::DataLayout 
&dataLayout,
 }
 
 
//===----------------------------------------------------------------------===//
-//  Definitions
+//  ArrayType Definitions
 
//===----------------------------------------------------------------------===//
 
 llvm::TypeSize
@@ -667,6 +667,41 @@ ArrayType::getABIAlignment(const ::mlir::DataLayout 
&dataLayout,
   return dataLayout.getTypeABIAlignment(getEltType());
 }
 
+//===----------------------------------------------------------------------===//
+// VectorType Definitions
+//===----------------------------------------------------------------------===//
+
+llvm::TypeSize cir::VectorType::getTypeSizeInBits(
+    const ::mlir::DataLayout &dataLayout,
+    ::mlir::DataLayoutEntryListRef params) const {
+  return llvm::TypeSize::getFixed(
+      getSize() * dataLayout.getTypeSizeInBits(getElementType()));
+}
+
+uint64_t
+cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
+                                 ::mlir::DataLayoutEntryListRef params) const {
+  return llvm::NextPowerOf2(dataLayout.getTypeSizeInBits(*this));
+}
+
+mlir::LogicalResult cir::VectorType::verify(
+    llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
+    mlir::Type elementType, uint64_t size) {
+  if (size == 0)
+    return emitError() << "the number of vector elements must be non-zero";
+
+  // Check if it a valid FixedVectorType
+  if (mlir::isa<cir::PointerType, cir::FP128Type>(elementType))
+    return success();
+
+  // Check if it a valid VectorType
+  if (mlir::isa<cir::IntType>(elementType) ||
+      isAnyFloatingPointType(elementType))
+    return success();
+
+  return emitError() << "unsupported element type for CIR vector";
+}
+
 
//===----------------------------------------------------------------------===//
 // PointerType Definitions
 
//===----------------------------------------------------------------------===//

diff  --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 8bb27942d9646..102438c2ded02 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -19,6 +19,7 @@
 #include "mlir/Dialect/DLTI/DLTI.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
+#include "mlir/Dialect/LLVMIR/LLVMTypes.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/BuiltinDialect.h"
 #include "mlir/IR/BuiltinOps.h"
@@ -1392,6 +1393,10 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
         convertTypeForMemory(converter, dataLayout, type.getEltType());
     return mlir::LLVM::LLVMArrayType::get(ty, type.getSize());
   });
+  converter.addConversion([&](cir::VectorType type) -> mlir::Type {
+    const mlir::Type ty = converter.convertType(type.getElementType());
+    return mlir::VectorType::get(type.getSize(), ty);
+  });
   converter.addConversion([&](cir::BoolType type) -> mlir::Type {
     return mlir::IntegerType::get(type.getContext(), 1,
                                   mlir::IntegerType::Signless);

diff  --git a/clang/test/CIR/CodeGen/vector-ext.cpp 
b/clang/test/CIR/CodeGen/vector-ext.cpp
new file mode 100644
index 0000000000000..13726edf3d259
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vector-ext.cpp
@@ -0,0 +1,73 @@
+// 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 int vi4 __attribute__((ext_vector_type(4)));
+typedef int vi3 __attribute__((ext_vector_type(3)));
+typedef int vi2 __attribute__((ext_vector_type(2)));
+typedef double vd2 __attribute__((ext_vector_type(2)));
+
+vi4 vec_a;
+// CIR: cir.global external @[[VEC_A:.*]] = #cir.zero : !cir.vector<4 x !s32i>
+
+// LLVM: @[[VEC_A:.*]] = dso_local global <4 x i32> zeroinitializer
+
+// OGCG: @[[VEC_A:.*]] = global <4 x i32> zeroinitializer
+
+vi3 vec_b;
+// CIR: cir.global external @[[VEC_B:.*]] = #cir.zero : !cir.vector<3 x !s32i>
+
+// LLVM: @[[VEC_B:.*]] = dso_local global <3 x i32> zeroinitializer
+
+// OGCG: @[[VEC_B:.*]] = global <3 x i32> zeroinitializer
+
+vi2 vec_c;
+// CIR: cir.global external @[[VEC_C:.*]] = #cir.zero : !cir.vector<2 x !s32i>
+
+// LLVM: @[[VEC_C:.*]] = dso_local global <2 x i32> zeroinitializer
+
+// OGCG: @[[VEC_C:.*]] = global <2 x i32> zeroinitializer
+
+vd2 d;
+
+// CIR: cir.global external @[[VEC_D:.*]] = #cir.zero : !cir.vector<2 x 
!cir.double>
+
+// LLVM: @[[VEC_D:.*]] = dso_local global <2 x double> zeroinitialize
+
+// OGCG: @[[VEC_D:.*]] = global <2 x double> zeroinitializer
+
+void foo() {
+  vi4 a;
+  vi3 b;
+  vi2 c;
+  vd2 d;
+}
+
+// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<3 x !s32i>, 
!cir.ptr<!cir.vector<3 x !s32i>>, ["b"]
+// CIR: %[[VEC_C:.*]] = cir.alloca !cir.vector<2 x !s32i>, 
!cir.ptr<!cir.vector<2 x !s32i>>, ["c"]
+// CIR: %[[VEC_D:.*]] = cir.alloca !cir.vector<2 x !cir.double>, 
!cir.ptr<!cir.vector<2 x !cir.double>>, ["d"]
+
+// LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[VEC_B:.*]] = alloca <3 x i32>, i64 1, align 16
+// LLVM: %[[VEC_C:.*]] = alloca <2 x i32>, i64 1, align 8
+// LLVM: %[[VEC_D:.*]] = alloca <2 x double>, i64 1, align 16
+
+// OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[VEC_B:.*]] = alloca <3 x i32>, align 16
+// OGCG: %[[VEC_C:.*]] = alloca <2 x i32>, align 8
+// OGCG: %[[VEC_D:.*]] = alloca <2 x double>, align 16
+
+void foo2(vi4 p) {}
+
+// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["p", init]
+// CIR: cir.store %{{.*}}, %[[VEC_A]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
+
+// LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: store <4 x i32> %{{.*}}, ptr %[[VEC_A]], align 16
+
+// OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
+// OGCG: store <4 x i32> %{{.*}}, ptr %[[VEC_A]], align 16

diff  --git a/clang/test/CIR/CodeGen/vector.cpp 
b/clang/test/CIR/CodeGen/vector.cpp
new file mode 100644
index 0000000000000..8f9e98fb6b3c0
--- /dev/null
+++ b/clang/test/CIR/CodeGen/vector.cpp
@@ -0,0 +1,60 @@
+// 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 int vi4 __attribute__((vector_size(16)));
+typedef double vd2 __attribute__((vector_size(16)));
+typedef long long vll2 __attribute__((vector_size(16)));
+
+vi4 vec_a;
+// CIR: cir.global external @[[VEC_A:.*]] = #cir.zero : !cir.vector<4 x !s32i>
+
+// LLVM: @[[VEC_A:.*]] = dso_local global <4 x i32> zeroinitializer
+
+// OGCG: @[[VEC_A:.*]] = global <4 x i32> zeroinitializer
+
+vd2 b;
+// CIR: cir.global external @[[VEC_B:.*]] = #cir.zero : !cir.vector<2 x 
!cir.double>
+
+// LLVM: @[[VEC_B:.*]] = dso_local global <2 x double> zeroinitialize
+
+// OGCG: @[[VEC_B:.*]] = global <2 x double> zeroinitializer
+
+vll2 c;
+// CIR: cir.global external @[[VEC_C:.*]] = #cir.zero : !cir.vector<2 x !s64i>
+
+// LLVM: @[[VEC_C:.*]] = dso_local global <2 x i64> zeroinitialize
+
+// OGCG: @[[VEC_C:.*]] = global <2 x i64> zeroinitializer
+
+void vec_int_test() {
+  vi4 a;
+  vd2 b;
+  vll2 c;
+}
+
+// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["a"]
+// CIR: %[[VEC_B:.*]] = cir.alloca !cir.vector<2 x !cir.double>, 
!cir.ptr<!cir.vector<2 x !cir.double>>, ["b"]
+// CIR: %[[VEC_C:.*]] = cir.alloca !cir.vector<2 x !s64i>, 
!cir.ptr<!cir.vector<2 x !s64i>>, ["c"]
+
+// LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: %[[VEC_B:.*]] = alloca <2 x double>, i64 1, align 16
+// LLVM: %[[VEC_C:.*]] = alloca <2 x i64>, i64 1, align 16
+
+// OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
+// OGCG: %[[VEC_B:.*]] = alloca <2 x double>, align 16
+// OGCG: %[[VEC_C:.*]] = alloca <2 x i64>, align 16
+
+void foo2(vi4 p) {}
+
+// CIR: %[[VEC_A:.*]] = cir.alloca !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>, ["p", init]
+// CIR: cir.store %{{.*}}, %[[VEC_A]] : !cir.vector<4 x !s32i>, 
!cir.ptr<!cir.vector<4 x !s32i>>
+
+// LLVM: %[[VEC_A:.*]] = alloca <4 x i32>, i64 1, align 16
+// LLVM: store <4 x i32> %{{.*}}, ptr %[[VEC_A]], align 16
+
+// OGCG: %[[VEC_A:.*]] = alloca <4 x i32>, align 16
+// OGCG: store <4 x i32> %{{.*}}, ptr %[[VEC_A]], align 16

diff  --git a/clang/test/CIR/IR/invalid-vector-zero-size.cir 
b/clang/test/CIR/IR/invalid-vector-zero-size.cir
new file mode 100644
index 0000000000000..ffe6c56a28aa1
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-vector-zero-size.cir
@@ -0,0 +1,10 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!s32i = !cir.int<s, 32>
+
+module  {
+
+// expected-error @below {{the number of vector elements must be non-zero}}
+cir.global external @vec_a = #cir.zero : !cir.vector<0 x !s32i>
+
+}

diff  --git a/clang/test/CIR/IR/invalid-vector.cir 
b/clang/test/CIR/IR/invalid-vector.cir
new file mode 100644
index 0000000000000..d94eacedec1f5
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-vector.cir
@@ -0,0 +1,10 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!s32i = !cir.int<s, 32>
+
+module  {
+
+// expected-error @below {{unsupported element type for CIR vector}}
+cir.global external @vec_b = #cir.zero : !cir.vector<4 x !cir.array<!s32i x 
10>>
+
+}

diff  --git a/clang/test/CIR/IR/vector.cir b/clang/test/CIR/IR/vector.cir
new file mode 100644
index 0000000000000..74ddf7691e7d4
--- /dev/null
+++ b/clang/test/CIR/IR/vector.cir
@@ -0,0 +1,40 @@
+// RUN: cir-opt %s | FileCheck %s
+
+!s32i = !cir.int<s, 32>
+
+module  {
+
+cir.global external @vec_a = #cir.zero : !cir.vector<4 x !s32i>
+// CHECK: cir.global external @vec_a = #cir.zero : !cir.vector<4 x !s32i>
+
+cir.global external @vec_b = #cir.zero : !cir.vector<3 x !s32i>
+// CHECK: cir.global external @vec_b = #cir.zero : !cir.vector<3 x !s32i>
+
+cir.global external @vec_c = #cir.zero : !cir.vector<2 x !s32i>
+// CHECK: cir.global external @vec_c = #cir.zero : !cir.vector<2 x !s32i>
+
+cir.func @vec_int_test() {
+  %0 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x !s32i>>, 
["a"]
+  %1 = cir.alloca !cir.vector<3 x !s32i>, !cir.ptr<!cir.vector<3 x !s32i>>, 
["b"]
+  %2 = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x !s32i>>, 
["c"]
+  cir.return
+}
+
+// CHECK: cir.func @vec_int_test() {
+// CHECK:  %0 = cir.alloca !cir.vector<4 x !s32i>, !cir.ptr<!cir.vector<4 x 
!s32i>>, ["a"]
+// CHECK:  %1 = cir.alloca !cir.vector<3 x !s32i>, !cir.ptr<!cir.vector<3 x 
!s32i>>, ["b"]
+// CHECK:  %2 = cir.alloca !cir.vector<2 x !s32i>, !cir.ptr<!cir.vector<2 x 
!s32i>>, ["c"]
+// CHECK:  cir.return
+// CHECK: }
+
+cir.func @vec_double_test() {
+  %0 = cir.alloca !cir.vector<2 x !cir.double>, !cir.ptr<!cir.vector<2 x 
!cir.double>>, ["a"]
+  cir.return
+}
+
+// CHECK: cir.func @vec_double_test() {
+// CHECK:  %0 = cir.alloca !cir.vector<2 x !cir.double>, 
!cir.ptr<!cir.vector<2 x !cir.double>>, ["a"]
+// CHECK:  cir.return
+// CHECK: }
+
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to