https://github.com/MacDue updated 
https://github.com/llvm/llvm-project/pull/231906

>From 719f1f3aa27f865062194322780b46279f09d478 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <[email protected]>
Date: Wed, 14 Oct 2026 12:35:30 +0000
Subject: [PATCH] [CIR] Use `llvm::ElementCount` to hold `cir::VectorType` size

A separate scalability flag is a design issue inherited from MLIR. It
makes dropping/ignoring scalability an easy mistake to make in common
transforms and lowerings.

This patch aligns ClangIR with LLVM and uses `ElementCount` to hold
the vector size. This makes it simple to propagate the entire size
(element count and scalability) and forces users to query the size they
expect:

- `.getFixedValue()`
  - Asserts the size is fixed and converts it to an integer
- `.getKnownMinValue()`
  - Allowed for fixed/scalable vectors
  - Returns the element count at vscale=1

A few small bugs/missed verifier checks have been handled with this patch
and are now tested:

- Don't fold scalable splats into fixed-vector-only constants
- Verify vectors are not scalable for fixed-vector-only operations
- Preserve scalable `TypeSize` values in CIRDataLayout and lowering

Assisted-by: Codex
---
 clang/include/clang/CIR/Dialect/IR/CIRTypes.h |  1 +
 .../include/clang/CIR/Dialect/IR/CIRTypes.td  | 21 +++--
 .../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp  | 70 ++++++++------
 clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp    | 92 +++++++++++--------
 clang/lib/CIR/CodeGen/CIRGenExpr.cpp          |  3 +-
 clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp    | 26 +++---
 clang/lib/CIR/CodeGen/CIRGenTypes.cpp         | 52 +++++------
 clang/lib/CIR/Dialect/IR/CIRAttrs.cpp         |  5 +-
 clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp    |  2 +-
 clang/lib/CIR/Dialect/IR/CIRDialect.cpp       | 20 +++-
 clang/lib/CIR/Dialect/IR/CIRTypes.cpp         | 37 ++++----
 .../CIR/Dialect/Transforms/CIRSimplify.cpp    |  5 +-
 .../Transforms/CallConvLoweringPass.cpp       |  9 +-
 .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 41 +++++----
 clang/test/CIR/IR/invalid-vector.cir          | 39 ++++++++
 clang/test/CIR/Lowering/not.cir               | 14 +++
 clang/test/CIR/Transforms/vector-splat.cir    | 11 +++
 llvm/include/llvm/Support/TypeSize.h          |  5 +
 18 files changed, 293 insertions(+), 160 deletions(-)

diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
index 19f86e83954367..ded2921c608c6f 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.h
@@ -26,6 +26,7 @@
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/TypeSize.h"
 
 namespace llvm {
 struct fltSemantics;
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td 
b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 366a4669c3a56f..2f61cbf2e6f97c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -478,7 +478,7 @@ def CIR_ArrayType : CIR_Type<"Array", "array", [
 }
 
 
//===----------------------------------------------------------------------===//
-// VectorType (fixed size)
+// VectorType
 
//===----------------------------------------------------------------------===//
 
 def CIR_VectorType : CIR_Type<"Vector", "vector", [
@@ -488,8 +488,9 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
   let summary = "CIR vector type";
   let description = [{
     The `!cir.vector` type represents a one-dimensional vector.
-    It takes three parameters: the element type, the number of elements and the
-    scalability flag (optional, defaults to `false`).
+    It takes two parameters: the element type and an element count, which
+    records both the known minimum number of elements and whether the vector is
+    scalable.
 
     Syntax:
 
@@ -524,16 +525,20 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
 
   let parameters = (ins
     CIR_VectorElementType:$element_type,
-    "uint64_t":$size,
-    OptionalParameter<"bool">:$is_scalable
+    "llvm::ElementCount":$size
   );
 
   let builders = [
     TypeBuilderWithInferredContext<(ins
-      "mlir::Type":$element_type, "uint64_t":$size, CArg<"bool",
-      "false">:$is_scalable
+      "mlir::Type":$element_type, "llvm::ElementCount":$size
     ), [{
-        return $_get(element_type.getContext(), element_type, size, 
is_scalable);
+        return $_get(element_type.getContext(), element_type, size);
+    }]>,
+    TypeBuilderWithInferredContext<(ins
+      "mlir::Type":$element_type, "uint64_t":$size
+    ), [{
+        return $_get(element_type.getContext(), element_type,
+                     llvm::ElementCount::getFixed(size));
     }]>,
   ];
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index ba7355cffbaf04..0dd1dd741984c4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -210,7 +210,7 @@ static mlir::Value emitNeonCall(CIRGenModule &cgm, 
CIRGenBuilderTy &builder,
 static cir::VectorType getNeonPairwiseWidenInputType(cir::VectorType resType,
                                                      bool usgn) {
   mlir::Type elemTy = resType.getElementType();
-  uint64_t resLanes = resType.getSize();
+  uint64_t resLanes = resType.getSize().getFixedValue();
   auto intTy = mlir::dyn_cast<cir::IntType>(elemTy);
   assert(intTy && "vpaddl result type must be an integer vector");
 
@@ -632,7 +632,7 @@ emitAArch64CompareBuiltinExpr(CIRGenFunction &cgf, 
CIRGenBuilderTy &builder,
 
   bool scalarCmp = !isa<cir::VectorType>(src.getType());
   if (!scalarCmp) {
-    assert(!cast<cir::VectorType>(retTy).getIsScalable() &&
+    assert(!cast<cir::VectorType>(retTy).getSize().isScalable() &&
            "This is only intended for fixed-width vectors");
     // Vector types are cast to i8 vectors. Recover original type.
     src = builder.createBitcast(src, retTy);
@@ -906,7 +906,7 @@ static mlir::Value emitCommonNeonBuiltinExpr(
   case NEON::BI__builtin_neon_splat_laneq_v:
   case NEON::BI__builtin_neon_splatq_lane_v:
   case NEON::BI__builtin_neon_splatq_laneq_v: {
-    uint64_t numElements = vTy.getSize();
+    uint64_t numElements = vTy.getSize().getFixedValue();
     if (builtinID == NEON::BI__builtin_neon_splatq_lane_v)
       numElements *= 2;
     if (builtinID == NEON::BI__builtin_neon_splat_laneq_v)
@@ -1511,8 +1511,8 @@ mlir::Value 
CIRGenFunction::emitSVEPredicateCast(mlir::Value pred,
 
   // TODO: Handle "aarch64.svcount" once we get round to supporting SME.
 
-  auto retTy = cir::VectorType::get(builder.getUIntNTy(1), minNumElts,
-                                    /*is_scalable=*/true);
+  auto retTy = cir::VectorType::get(
+      builder.getUIntNTy(1), llvm::ElementCount::getScalable(minNumElts));
   if (pred.getType() == retTy)
     return pred;
 
@@ -1585,33 +1585,46 @@ cir::VectorType CIRGenFunction::getSVEType(const 
SVETypeFlags &typeFlags) {
     llvm_unreachable("Invalid SVETypeFlag!");
 
   case SVETypeFlags::EltTyInt8:
-    return cir::VectorType::get(builder.getUInt8Ty(), 16, true);
+    return cir::VectorType::get(builder.getUInt8Ty(),
+                                llvm::ElementCount::getScalable(16));
   case SVETypeFlags::EltTyInt16:
-    return cir::VectorType::get(builder.getUInt16Ty(), 8, true);
+    return cir::VectorType::get(builder.getUInt16Ty(),
+                                llvm::ElementCount::getScalable(8));
   case SVETypeFlags::EltTyInt32:
-    return cir::VectorType::get(builder.getUInt32Ty(), 4, true);
+    return cir::VectorType::get(builder.getUInt32Ty(),
+                                llvm::ElementCount::getScalable(4));
   case SVETypeFlags::EltTyInt64:
-    return cir::VectorType::get(builder.getUInt64Ty(), 2, true);
+    return cir::VectorType::get(builder.getUInt64Ty(),
+                                llvm::ElementCount::getScalable(2));
 
   case SVETypeFlags::EltTyMFloat8:
-    return cir::VectorType::get(builder.getUInt8Ty(), 16, true);
+    return cir::VectorType::get(builder.getUInt8Ty(),
+                                llvm::ElementCount::getScalable(16));
   case SVETypeFlags::EltTyFloat16:
-    return cir::VectorType::get(builder.getFp16Ty(), 8, true);
+    return cir::VectorType::get(builder.getFp16Ty(),
+                                llvm::ElementCount::getScalable(8));
   case SVETypeFlags::EltTyBFloat16:
-    return cir::VectorType::get(builder.getBF16Type(), 8, true);
+    return cir::VectorType::get(builder.getBF16Type(),
+                                llvm::ElementCount::getScalable(8));
   case SVETypeFlags::EltTyFloat32:
-    return cir::VectorType::get(builder.getF32Type(), 4, true);
+    return cir::VectorType::get(builder.getF32Type(),
+                                llvm::ElementCount::getScalable(4));
   case SVETypeFlags::EltTyFloat64:
-    return cir::VectorType::get(builder.getDoubleTy(), 2, true);
+    return cir::VectorType::get(builder.getDoubleTy(),
+                                llvm::ElementCount::getScalable(2));
 
   case SVETypeFlags::EltTyBool8:
-    return cir::VectorType::get(builder.getUIntNTy(1), 16, true);
+    return cir::VectorType::get(builder.getUIntNTy(1),
+                                llvm::ElementCount::getScalable(16));
   case SVETypeFlags::EltTyBool16:
-    return cir::VectorType::get(builder.getUIntNTy(1), 8, true);
+    return cir::VectorType::get(builder.getUIntNTy(1),
+                                llvm::ElementCount::getScalable(8));
   case SVETypeFlags::EltTyBool32:
-    return cir::VectorType::get(builder.getUIntNTy(1), 4, true);
+    return cir::VectorType::get(builder.getUIntNTy(1),
+                                llvm::ElementCount::getScalable(4));
   case SVETypeFlags::EltTyBool64:
-    return cir::VectorType::get(builder.getUIntNTy(1), 2, true);
+    return cir::VectorType::get(builder.getUIntNTy(1),
+                                llvm::ElementCount::getScalable(2));
   }
 }
 
@@ -1622,7 +1635,7 @@ static cir::VectorType 
getSVEVectorForElementType(CIRGenModule &cgm,
                                                   mlir::Type eltTy) {
   unsigned numElts =
       sveBitsPerBlock / cgm.getDataLayout().getTypeSizeInBits(eltTy);
-  return cir::VectorType::get(eltTy, numElts, /*is_scalable=*/true);
+  return cir::VectorType::get(eltTy, llvm::ElementCount::getScalable(numElts));
 }
 
 
//===----------------------------------------------------------------------===//
@@ -3203,10 +3216,11 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
     // same shape as the result vector.
     cir::VectorType sourceTy = cir::VectorType::get(
         ty.getElementType(), builtinID == NEON::BI__builtin_neon_vfmaq_lane_v
-                                 ? ty.getSize() / 2
-                                 : ty.getSize());
+                                 ? ty.getSize().getFixedValue() / 2
+                                 : ty.getSize().getFixedValue());
     mlir::Value laneSource = builder.createBitcast(ops[2], sourceTy);
-    laneSource = emitNeonSplat(builder, loc, laneSource, ops[3], ty.getSize());
+    laneSource = emitNeonSplat(builder, loc, laneSource, ops[3],
+                               ty.getSize().getFixedValue());
 
     llvm::SmallVector<mlir::Value> fmaOps = {multiplicand, laneSource, addend};
     return emitNeonCallToOp<cir::FMAOp>(cgm, builder, {ty, ty, ty}, fmaOps,
@@ -3241,7 +3255,8 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
     cir::VectorType sourceTy =
         cir::VectorType::get(ty.getElementType(), ty.getSize() * 2);
     mlir::Value laneSource = builder.createBitcast(ops[2], sourceTy);
-    laneSource = emitNeonSplat(builder, loc, laneSource, ops[3], ty.getSize());
+    laneSource = emitNeonSplat(builder, loc, laneSource, ops[3],
+                               ty.getSize().getFixedValue());
 
     llvm::SmallVector<mlir::Value> fmaOps = {laneSource, multiplicand, addend};
     return emitNeonCallToOp<cir::FMAOp>(cgm, builder, {ty, ty, ty}, fmaOps,
@@ -3251,7 +3266,8 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
     mlir::Value addend = builder.createBitcast(ops[0], ty);
     mlir::Value multiplicand = builder.createBitcast(ops[1], ty);
     mlir::Value laneSource = builder.createBitcast(ops[2], ty);
-    laneSource = emitNeonSplat(builder, loc, laneSource, ops[3], ty.getSize());
+    laneSource = emitNeonSplat(builder, loc, laneSource, ops[3],
+                               ty.getSize().getFixedValue());
 
     llvm::SmallVector<mlir::Value> fmaOps = {laneSource, multiplicand, addend};
     return emitNeonCallToOp<cir::FMAOp>(cgm, builder, {ty, ty, ty}, fmaOps,
@@ -3843,7 +3859,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
 
     for (unsigned vi = 0; vi != 2; ++vi) {
       llvm::SmallVector<int64_t, 16> indices;
-      for (unsigned i = 0, e = ty.getSize(); i != e; i += 2) {
+      for (unsigned i = 0, e = ty.getSize().getFixedValue(); i != e; i += 2) {
         indices.push_back(i + vi);
         indices.push_back(i + e + vi);
       }
@@ -3864,7 +3880,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
     mlir::Value sv;
     for (unsigned vi = 0; vi != 2; ++vi) {
       llvm::SmallVector<int64_t, 16> indices;
-      for (unsigned i = 0, e = ty.getSize(); i != e; ++i) {
+      for (unsigned i = 0, e = ty.getSize().getFixedValue(); i != e; ++i) {
         indices.push_back(2 * i + vi);
       }
       cir::ConstantOp idx = builder.getConstInt(loc, builder.getSInt32Ty(), 
vi);
@@ -3884,7 +3900,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned 
builtinID, const CallExpr *expr,
     mlir::Value sv;
     for (unsigned vi = 0; vi != 2; ++vi) {
       llvm::SmallVector<int64_t, 16> indices;
-      for (unsigned i = 0, e = ty.getSize(); i != e; i += 2) {
+      for (unsigned i = 0, e = ty.getSize().getFixedValue(); i != e; i += 2) {
         indices.push_back((i + vi * e) >> 1);
         indices.push_back(((i + vi * e) >> 1) + e);
       }
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp 
b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
index febcaa7459edb0..50c88064edf948 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp
@@ -91,7 +91,7 @@ static mlir::Value emitX86CompressStore(CIRGenBuilderTy 
&builder,
                                         ArrayRef<mlir::Value> ops) {
   auto resultTy = cast<cir::VectorType>(ops[1].getType());
   mlir::Value maskValue =
-      getMaskVecValue(builder, loc, ops[2], resultTy.getSize());
+      getMaskVecValue(builder, loc, ops[2], 
resultTy.getSize().getFixedValue());
 
   return builder.emitIntrinsicCallOp(
       loc, "masked.compressstore", cir::VoidType::get(builder.getContext()),
@@ -113,7 +113,7 @@ static cir::VecShuffleOp emitPshufWord(CIRGenBuilderTy 
&builder,
   uint32_t imm = CIRGenFunction::getZExtIntValueFromConstOp(immediate);
 
   auto vecTy = cast<cir::VectorType>(vec.getType());
-  unsigned numElts = vecTy.getSize();
+  unsigned numElts = vecTy.getSize().getFixedValue();
 
   unsigned firstHalfStart = isLow ? 0 : 4;
   unsigned secondHalfStart = 4 - firstHalfStart;
@@ -141,7 +141,7 @@ computeFullLaneShuffleMask(CIRGenFunction &cgf, const 
mlir::Value vec,
                            uint32_t imm, const bool isShufP,
                            llvm::SmallVectorImpl<int64_t> &outIndices) {
   auto vecTy = cast<cir::VectorType>(vec.getType());
-  unsigned numElts = vecTy.getSize();
+  unsigned numElts = vecTy.getSize().getFixedValue();
   unsigned numLanes = cgf.cgm.getDataLayout().getTypeSizeInBits(vecTy) / 128;
   unsigned numLaneElts = numElts / numLanes;
 
@@ -194,7 +194,8 @@ static mlir::Value emitX86CompressExpand(CIRGenBuilderTy 
&builder,
                                          const std::string &id) {
   auto resultTy = cast<cir::VectorType>(mask.getType());
   mlir::Value maskValue = getMaskVecValue(
-      builder, loc, inputVector, cast<cir::VectorType>(resultTy).getSize());
+      builder, loc, inputVector,
+      cast<cir::VectorType>(resultTy).getSize().getFixedValue());
   return builder.emitIntrinsicCallOp(loc, id, resultTy,
                                      mlir::ValueRange{source, mask, 
maskValue});
 }
@@ -234,8 +235,9 @@ static mlir::Value emitX86Select(CIRGenBuilderTy &builder, 
mlir::Location loc,
   if (constOp && constOp.isAllOnesValue())
     return op0;
 
-  mask = getMaskVecValue(builder, loc, mask,
-                         cast<cir::VectorType>(op0.getType()).getSize());
+  mask = getMaskVecValue(
+      builder, loc, mask,
+      cast<cir::VectorType>(op0.getType()).getSize().getFixedValue());
 
   return cir::VecTernaryOp::create(builder, loc, mask, op0, op1);
 }
@@ -385,7 +387,8 @@ emitX86MaskedCompare(CIRGenBuilderTy &builder, unsigned cc, 
bool isSigned,
                      ArrayRef<mlir::Value> ops, mlir::Location loc) {
   assert((ops.size() == 2 || ops.size() == 4) &&
          "Unexpected number of arguments");
-  unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+  unsigned numElts =
+      cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
   mlir::Value cmp;
   if (cc == 3) {
     cmp = builder.getNullValue(
@@ -447,7 +450,8 @@ static std::optional<mlir::Value> 
emitX86SExtMask(CIRGenBuilderTy &builder,
                                                   mlir::Value op,
                                                   mlir::Type dstTy,
                                                   mlir::Location loc) {
-  unsigned numberOfElements = cast<cir::VectorType>(dstTy).getSize();
+  unsigned numberOfElements =
+      cast<cir::VectorType>(dstTy).getSize().getFixedValue();
   mlir::Value mask = getMaskVecValue(builder, loc, op, numberOfElements);
 
   return builder.createCast(loc, cir::CastKind::integral, mask, dstTy);
@@ -456,7 +460,8 @@ static std::optional<mlir::Value> 
emitX86SExtMask(CIRGenBuilderTy &builder,
 static mlir::Value emitVecInsert(CIRGenBuilderTy &builder, mlir::Location loc,
                                  mlir::Value vec, mlir::Value value,
                                  mlir::Value indexOp) {
-  unsigned numElts = cast<cir::VectorType>(vec.getType()).getSize();
+  unsigned numElts =
+      cast<cir::VectorType>(vec.getType()).getSize().getFixedValue();
 
   uint64_t index =
       indexOp.getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
@@ -479,7 +484,7 @@ static mlir::Value emitX86FunnelShift(CIRGenBuilderTy 
&builder,
   // so we only care about the lowest log2 bits anyway.
   if (amt.getType() != op0Ty) {
     auto vecTy = mlir::cast<cir::VectorType>(op0Ty);
-    uint64_t numElems = vecTy.getSize();
+    uint64_t numElems = vecTy.getSize().getFixedValue();
 
     auto amtTy = mlir::cast<cir::IntType>(amt.getType());
     auto vecElemTy = mlir::cast<cir::IntType>(vecTy.getElementType());
@@ -554,11 +559,12 @@ static mlir::Value 
emitX86CvtF16ToFloatExpr(CIRGenBuilderTy &builder,
     }
   }
 
-  unsigned numElts = cast<cir::VectorType>(dstTy).getSize();
+  unsigned numElts = cast<cir::VectorType>(dstTy).getSize().getFixedValue();
   mlir::Value src = ops[0];
 
   // Extract the subvector
-  if (numElts != cast<cir::VectorType>(src.getType()).getSize()) {
+  if (numElts !=
+      cast<cir::VectorType>(src.getType()).getSize().getFixedValue()) {
     assert(numElts == 4 && "Unexpected vector size");
     src = builder.createVecShuffle(loc, src, {0, 1, 2, 3});
   }
@@ -635,7 +641,8 @@ static mlir::Value emitX86vpcom(CIRGenBuilderTy &builder, 
mlir::Location loc,
 static mlir::Value emitX86Fpclass(CIRGenBuilderTy &builder, mlir::Location loc,
                                   unsigned builtinID,
                                   SmallVectorImpl<mlir::Value> &ops) {
-  unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+  unsigned numElts =
+      cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
   mlir::Value maskIn = ops[2];
   ops.erase(ops.begin() + 2);
 
@@ -810,8 +817,9 @@ static mlir::Value emitX86MaskedLoad(CIRGenBuilderTy 
&builder,
                                      mlir::Location loc) {
   mlir::Type ty = ops[1].getType();
   mlir::Value ptr = ops[0];
-  mlir::Value maskVec = getMaskVecValue(builder, loc, ops[2],
-                                        cast<cir::VectorType>(ty).getSize());
+  mlir::Value maskVec =
+      getMaskVecValue(builder, loc, ops[2],
+                      cast<cir::VectorType>(ty).getSize().getFixedValue());
 
   return builder.createMaskedLoad(loc, ty, ptr, alignment, maskVec, ops[1]);
 }
@@ -820,7 +828,7 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy 
&builder,
                                      mlir::Location loc,
                                      llvm::SmallVector<mlir::Value> ops) {
   auto inputType = cast<cir::VectorType>(ops[0].getType());
-  assert(!inputType.getIsScalable() &&
+  assert(!inputType.getSize().isScalable() &&
          "This is only intended for fixed-width vectors");
 
   const uint8_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]);
@@ -834,7 +842,7 @@ static mlir::Value emitX86VPerm2f128(CIRGenBuilderTy 
&builder,
   llvm::SmallVector<mlir::Attribute, 64> mask;
 
   cir::IntType i32Ty = builder.getSInt32Ty();
-  const unsigned numElts = inputType.getSize();
+  const unsigned numElts = inputType.getSize().getFixedValue();
   // We must evaluated each lane(128 bits) separetely
   for (auto lane : llvm::seq(0, 2)) {
     bool isZeroBit = imm & (1 << ((lane * 4) + 3)),
@@ -865,7 +873,7 @@ static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy 
&builder,
                                           llvm::ArrayRef<mlir::Value> ops,
                                           llvm::Boolean isLeftShift) {
   auto byteVecType = cast<cir::VectorType>(ops[0].getType());
-  assert(!byteVecType.getIsScalable() &&
+  assert(!byteVecType.getSize().isScalable() &&
          "This is only intended for fixed-width vectors");
 
   unsigned shiftVal = CIRGenFunction::getZExtIntValueFromConstOp(ops[1]) & 
0xFF;
@@ -877,7 +885,7 @@ static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy 
&builder,
   if (shiftVal >= 16)
     return zeroVector;
 
-  uint64_t numElts = byteVecType.getSize();
+  uint64_t numElts = byteVecType.getSize().getFixedValue();
   assert(numElts % 16 == 0 && "Expected a multiple of 16");
 
   llvm::SmallVector<int64_t, 64> shuffleMask;
@@ -1185,7 +1193,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_vec_ext_v16hi:
   case X86::BI__builtin_ia32_vec_ext_v8si:
   case X86::BI__builtin_ia32_vec_ext_v4di: {
-    unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
 
     uint64_t index = getZExtIntValueFromConstOp(ops[1]);
     index &= numElts - 1;
@@ -1673,9 +1682,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
     }
 
     mlir::Location loc = getLoc(expr->getExprLoc());
-    unsigned minElts =
-        std::min(cast<cir::VectorType>(ops[0].getType()).getSize(),
-                 cast<cir::VectorType>(ops[2].getType()).getSize());
+    unsigned minElts = std::min(
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue(),
+        cast<cir::VectorType>(ops[2].getType()).getSize().getFixedValue());
     ops[3] = getMaskVecValue(builder, loc, ops[3], minElts);
     return builder.emitIntrinsicCallOp(loc, intrinsicName,
                                        convertType(expr->getType()), ops);
@@ -1783,9 +1792,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
     }
 
     mlir::Location loc = getLoc(expr->getExprLoc());
-    unsigned minElts =
-        std::min(cast<cir::VectorType>(ops[2].getType()).getSize(),
-                 cast<cir::VectorType>(ops[3].getType()).getSize());
+    unsigned minElts = std::min(
+        cast<cir::VectorType>(ops[2].getType()).getSize().getFixedValue(),
+        cast<cir::VectorType>(ops[3].getType()).getSize().getFixedValue());
     ops[1] = getMaskVecValue(builder, loc, ops[1], minElts);
 
     return builder.emitIntrinsicCallOp(loc, intrinsicName,
@@ -1809,8 +1818,9 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_extracti64x2_512_mask: {
     mlir::Location loc = getLoc(expr->getExprLoc());
     cir::VectorType dstTy = 
cast<cir::VectorType>(convertType(expr->getType()));
-    unsigned numElts = dstTy.getSize();
-    unsigned srcNumElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts = dstTy.getSize().getFixedValue();
+    unsigned srcNumElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
     unsigned subVectors = srcNumElts / numElts;
     assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 
subvectors");
     unsigned index =
@@ -1847,8 +1857,10 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_inserti64x2_256:
   case X86::BI__builtin_ia32_insertf64x2_512:
   case X86::BI__builtin_ia32_inserti64x2_512: {
-    unsigned dstNumElts = cast<cir::VectorType>(ops[0].getType()).getSize();
-    unsigned srcNumElts = cast<cir::VectorType>(ops[1].getType()).getSize();
+    unsigned dstNumElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
+    unsigned srcNumElts =
+        cast<cir::VectorType>(ops[1].getType()).getSize().getFixedValue();
     unsigned subVectors = dstNumElts / srcNumElts;
     assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 
subvectors");
     assert(dstNumElts <= 16);
@@ -1890,7 +1902,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_pblendd128:
   case X86::BI__builtin_ia32_pblendd256: {
     uint32_t imm = getZExtIntValueFromConstOp(ops[2]);
-    unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
 
     llvm::SmallVector<mlir::Attribute, 16> indices;
     // If there are more than 8 elements, the immediate is used twice so make
@@ -1949,7 +1962,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_permdf512: {
     unsigned imm =
         ops[1].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
-    unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
 
     // These intrinsics operate on 256-bit lanes of four 64-bit elements.
     int64_t Indices[8];
@@ -1966,7 +1980,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_palignr512: {
     uint32_t shiftVal = getZExtIntValueFromConstOp(ops[2]) & 0xff;
 
-    unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
     assert(numElts % 16 == 0);
 
     // If palignr is shifting the pair of vectors more than the size of two
@@ -2004,7 +2019,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_alignq128:
   case X86::BI__builtin_ia32_alignq256:
   case X86::BI__builtin_ia32_alignq512: {
-    unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
     unsigned shiftVal =
         ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue() &
         0xff;
@@ -2034,7 +2050,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
     unsigned imm =
         ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue();
 
-    unsigned numElems = cast<cir::VectorType>(src1.getType()).getSize();
+    unsigned numElems =
+        cast<cir::VectorType>(src1.getType()).getSize().getFixedValue();
     unsigned totalBits = getContext().getTypeSize(expr->getArg(0)->getType());
     unsigned numLanes = totalBits == 512 ? 4 : 2;
     unsigned numElemsPerLane = numElems / numLanes;
@@ -2546,7 +2563,8 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
   case X86::BI__builtin_ia32_vp2intersect_d_512:
   case X86::BI__builtin_ia32_vp2intersect_d_256:
   case X86::BI__builtin_ia32_vp2intersect_d_128: {
-    unsigned numElts = cast<cir::VectorType>(ops[0].getType()).getSize();
+    unsigned numElts =
+        cast<cir::VectorType>(ops[0].getType()).getSize().getFixedValue();
     mlir::Location loc = getLoc(expr->getExprLoc());
     StringRef intrinsicName;
 
@@ -2687,7 +2705,7 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, 
const CallExpr *expr) {
     cir::VectorType resTy = 
cast<cir::VectorType>(convertType(expr->getType()));
 
     cir::VectorType inputTy = cast<cir::VectorType>(ops[0].getType());
-    unsigned numElts = inputTy.getSize();
+    unsigned numElts = inputTy.getSize().getFixedValue();
 
     mlir::Value mask = getMaskVecValue(builder, loc, ops[2], numElts);
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
index 9c71d987c37e16..bdf17087d89304 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp
@@ -350,7 +350,8 @@ void 
CIRGenFunction::emitStoreThroughExtVectorComponentLValue(RValue src,
   mlir::Value vec = builder.createLoad(loc, dstAddr, dst.isVolatile());
   if (const auto *vecTy = dst.getType()->getAs<clang::VectorType>()) {
     unsigned numSrcElts = vecTy->getNumElements();
-    unsigned numDstElts = cast<cir::VectorType>(vec.getType()).getSize();
+    unsigned numDstElts =
+        cast<cir::VectorType>(vec.getType()).getSize().getFixedValue();
     if (numDstElts == numSrcElts) {
       // Use shuffle vector is the src and destination are the same number of
       // elements and restore the vector mask since it is on the side it will 
be
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 8e8eea7c21ab55..a2c898b2e952ce 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -1619,12 +1619,14 @@ class ScalarExprEmitter : public 
StmtVisitor<ScalarExprEmitter, mlir::Value> {
     mlir::Type srcTy = src.getType();
     mlir::Type dstTy = cgf.convertType(e->getType());
 
-    unsigned numElementsSrc = isa<cir::VectorType>(srcTy)
-                                  ? cast<cir::VectorType>(srcTy).getSize()
-                                  : 0;
-    unsigned numElementsDst = isa<cir::VectorType>(dstTy)
-                                  ? cast<cir::VectorType>(dstTy).getSize()
-                                  : 0;
+    unsigned numElementsSrc =
+        isa<cir::VectorType>(srcTy)
+            ? cast<cir::VectorType>(srcTy).getSize().getFixedValue()
+            : 0;
+    unsigned numElementsDst =
+        isa<cir::VectorType>(dstTy)
+            ? cast<cir::VectorType>(dstTy).getSize().getFixedValue()
+            : 0;
 
     // Use bit vector expansion for ext_vector_type boolean vectors.
     if (e->getType()->isExtVectorBoolType()) {
@@ -2994,11 +2996,12 @@ mlir::Value 
ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) {
     }
 
     // Zero-initialize any remaining values.
-    if (numInitElements < vectorType.getSize()) {
+    const uint64_t vectorSize = vectorType.getSize().getFixedValue();
+    if (numInitElements < vectorSize) {
       const mlir::Value zeroValue = cgf.getBuilder().getNullValue(
           vectorType.getElementType(), cgf.getLoc(e->getSourceRange()));
-      std::fill_n(std::back_inserter(elements),
-                  vectorType.getSize() - numInitElements, zeroValue);
+      std::fill_n(std::back_inserter(elements), vectorSize - numInitElements,
+                  zeroValue);
     }
 
     return cir::VecCreateOp::create(cgf.getBuilder(),
@@ -3211,7 +3214,7 @@ mlir::Value 
ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
     return builder.getConstantInt(loc, cgf.cgm.sizeTy, alignment);
   } else if (e->getKind() == UETT_VectorElements) {
     auto vecTy = cast<cir::VectorType>(convertType(e->getTypeOfArgument()));
-    if (vecTy.getIsScalable()) {
+    if (vecTy.getSize().isScalable()) {
       cgf.getCIRGenModule().errorNYI(
           e->getSourceRange(),
           "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector");
@@ -3221,7 +3224,8 @@ mlir::Value 
ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr(
     }
 
     return builder.getConstant(
-        loc, cir::IntAttr::get(cgf.cgm.sizeTy, vecTy.getSize()));
+        loc,
+        cir::IntAttr::get(cgf.cgm.sizeTy, vecTy.getSize().getFixedValue()));
   }
 
   // The result type is size_t (target-dependent width); use it so the IntAttr
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp 
b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index e1da57c9a38db7..92817f32024002 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -378,56 +378,56 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
 
     // SVE types
     case BuiltinType::SveInt8:
-      resultType =
-          cir::VectorType::get(builder.getSInt8Ty(), 16, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getSInt8Ty(),
+                                        llvm::ElementCount::getScalable(16));
       break;
     case BuiltinType::SveUint8:
-      resultType =
-          cir::VectorType::get(builder.getUInt8Ty(), 16, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getUInt8Ty(),
+                                        llvm::ElementCount::getScalable(16));
       break;
     case BuiltinType::SveInt16:
-      resultType =
-          cir::VectorType::get(builder.getSInt16Ty(), 8, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getSInt16Ty(),
+                                        llvm::ElementCount::getScalable(8));
       break;
     case BuiltinType::SveUint16:
-      resultType =
-          cir::VectorType::get(builder.getUInt16Ty(), 8, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getUInt16Ty(),
+                                        llvm::ElementCount::getScalable(8));
       break;
     case BuiltinType::SveFloat16:
-      resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
-                                        /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getFp16Ty(),
+                                        llvm::ElementCount::getScalable(8));
       break;
     case BuiltinType::SveBFloat16:
-      resultType = cir::VectorType::get(builder.getBfloat16Ty(), 8,
-                                        /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getBfloat16Ty(),
+                                        llvm::ElementCount::getScalable(8));
       break;
     case BuiltinType::SveInt32:
-      resultType =
-          cir::VectorType::get(builder.getSInt32Ty(), 4, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getSInt32Ty(),
+                                        llvm::ElementCount::getScalable(4));
       break;
     case BuiltinType::SveUint32:
-      resultType =
-          cir::VectorType::get(builder.getUInt32Ty(), 4, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getUInt32Ty(),
+                                        llvm::ElementCount::getScalable(4));
       break;
     case BuiltinType::SveFloat32:
-      resultType = cir::VectorType::get(builder.getSingleTy(), 4,
-                                        /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getSingleTy(),
+                                        llvm::ElementCount::getScalable(4));
       break;
     case BuiltinType::SveInt64:
-      resultType =
-          cir::VectorType::get(builder.getSInt64Ty(), 2, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getSInt64Ty(),
+                                        llvm::ElementCount::getScalable(2));
       break;
     case BuiltinType::SveUint64:
-      resultType =
-          cir::VectorType::get(builder.getUInt64Ty(), 2, /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getUInt64Ty(),
+                                        llvm::ElementCount::getScalable(2));
       break;
     case BuiltinType::SveFloat64:
-      resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
-                                        /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getDoubleTy(),
+                                        llvm::ElementCount::getScalable(2));
       break;
     case BuiltinType::SveBool:
-      resultType = cir::VectorType::get(builder.getUIntNTy(1), 16,
-                                        /*is_scalable=*/true);
+      resultType = cir::VectorType::get(builder.getUIntNTy(1),
+                                        llvm::ElementCount::getScalable(16));
       break;
 
     // Unsigned integral types.
diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp 
b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
index 2649ed14497393..267fec81828e68 100644
--- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp
@@ -902,7 +902,10 @@ 
cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError,
 
   const auto vecType = mlir::cast<cir::VectorType>(type);
 
-  if (vecType.getSize() != elts.size())
+  if (vecType.getSize().isScalable())
+    return emitError() << "scalable vector constants are not supported";
+
+  if (vecType.getSize().getFixedValue() != elts.size())
     return emitError()
            << "number of constant elements should match vector size";
 
diff --git a/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
index 5ce0c8f8e7a2c6..2347edcfee161d 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp
@@ -56,5 +56,5 @@ llvm::TypeSize CIRDataLayout::getTypeSizeInBits(mlir::Type 
ty) const {
   assert(!cir::MissingFeatures::addressSpace());
 
   // This is calling mlir::DataLayout::getTypeSizeInBits().
-  return llvm::TypeSize::getFixed(layout.getTypeSizeInBits(ty));
+  return layout.getTypeSizeInBits(ty);
 }
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp 
b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 3088a39e5a4d0a..4da147ea5e0dfe 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -4161,10 +4161,14 @@ LogicalResult cir::VecCreateOp::verify() {
   // vector, and that the type of all the arguments matches the type of the
   // elements in the vector.
   const cir::VectorType vecTy = getType();
-  if (getElements().size() != vecTy.getSize()) {
+  if (vecTy.getSize().isScalable())
+    return emitOpError() << "scalable vectors are not supported";
+
+  if (getElements().size() != vecTy.getSize().getFixedValue()) {
     return emitOpError() << "operand count of " << getElements().size()
                          << " doesn't match vector type " << vecTy
-                         << " element count of " << vecTy.getSize();
+                         << " element count of "
+                         << vecTy.getSize().getFixedValue();
   }
 
   const mlir::Type elementType = vecTy.getElementType();
@@ -4401,9 +4405,14 @@ OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor 
adaptor) {
 }
 
 LogicalResult cir::VecShuffleOp::verify() {
+  if (getVec1().getType().getSize().isScalable() ||
+      getVec2().getType().getSize().isScalable() ||
+      getResult().getType().getSize().isScalable())
+    return emitOpError() << "scalable vectors are not supported";
+
   // The number of elements in the indices array must match the number of
   // elements in the result type.
-  if (getIndices().size() != getResult().getType().getSize()) {
+  if (getIndices().size() != getResult().getType().getSize().getFixedValue()) {
     return emitOpError() << ": the number of elements in " << getIndices()
                          << " and " << getResult().getType() << " don't match";
   }
@@ -4416,8 +4425,9 @@ LogicalResult cir::VecShuffleOp::verify() {
                          << " and " << getResult().getType() << " don't match";
   }
 
-  const uint64_t maxValidIndex =
-      getVec1().getType().getSize() + getVec2().getType().getSize() - 1;
+  const uint64_t maxValidIndex = getVec1().getType().getSize().getFixedValue() 
+
+                                 getVec2().getType().getSize().getFixedValue() 
-
+                                 1;
   if (llvm::any_of(
           getIndices().getAsRange<cir::IntAttr>(), [&](cir::IntAttr idxAttr) {
             return idxAttr.getSInt() != -1 && idxAttr.getUInt() > 
maxValidIndex;
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp 
b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 061d15cc3a0885..545f3668df873e 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -1496,32 +1496,35 @@ llvm::TypeSize cir::VectorType::getTypeSizeInBits(
     ::mlir::DataLayoutEntryListRef params) const {
   // Clang packs a fixed-length bool vector one bit per element and rounds the
   // vector's size up to a power of two of at least a byte.
-  if (mlir::isa<cir::BoolType>(getElementType()) && !getIsScalable()) {
+  if (mlir::isa<cir::BoolType>(getElementType()) && getSize().isFixed()) {
     assert(!cir::MissingFeatures::hlsl());
     return llvm::TypeSize::getFixed(llvm::PowerOf2Ceil(getBoolStorageWidth()));
   }
-  return llvm::TypeSize::getFixed(
-      getSize() * dataLayout.getTypeSizeInBits(getElementType()));
+
+  llvm::TypeSize elementSize = dataLayout.getTypeSizeInBits(getElementType());
+  return llvm::TypeSize::get(getSize().getKnownMinValue() *
+                                 elementSize.getFixedValue(),
+                             getSize().isScalable());
 }
 
 uint64_t cir::VectorType::getBoolStorageWidth() const {
   assert(mlir::isa<cir::BoolType>(getElementType()) &&
          "only a bool vector is stored as an integer");
-  return std::max<uint64_t>(getSize(), 8);
+  return std::max<uint64_t>(getSize().getFixedValue(), 8);
 }
 
 uint64_t
 cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
                                  ::mlir::DataLayoutEntryListRef params) const {
   // This hook answers in bytes, not bits.
-  return llvm::PowerOf2Ceil(
-      llvm::divideCeil(dataLayout.getTypeSizeInBits(*this), 8u));
+  return llvm::PowerOf2Ceil(llvm::divideCeil(
+      dataLayout.getTypeSizeInBits(*this).getKnownMinValue(), uint64_t{8}));
 }
 
 mlir::LogicalResult cir::VectorType::verify(
     llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
-    mlir::Type elementType, uint64_t size, bool scalable) {
-  if (size == 0)
+    mlir::Type elementType, llvm::ElementCount size) {
+  if (size.isZero())
     return emitError() << "the number of vector elements must be non-zero";
   return success();
 }
@@ -1532,7 +1535,7 @@ mlir::Type cir::VectorType::parse(::mlir::AsmParser 
&odsParser) {
   mlir::Builder odsBuilder(odsParser.getContext());
   mlir::FailureOr<::mlir::Type> elementType;
   mlir::FailureOr<uint64_t> size;
-  bool isScalabe = false;
+  bool isScalable = false;
 
   // Parse literal '<'
   if (odsParser.parseLess())
@@ -1540,7 +1543,7 @@ mlir::Type cir::VectorType::parse(::mlir::AsmParser 
&odsParser) {
 
   // Parse literal '[', if present, and set the scalability flag accordingly
   if (odsParser.parseOptionalLSquare().succeeded())
-    isScalabe = true;
+    isScalable = true;
 
   // Parse variable 'size'
   size = mlir::FieldParser<uint64_t>::parse(odsParser);
@@ -1553,7 +1556,7 @@ mlir::Type cir::VectorType::parse(::mlir::AsmParser 
&odsParser) {
 
   // Parse literal ']', which is expected when dealing with scalable
   // dim sizes
-  if (isScalabe && odsParser.parseRSquare().failed()) {
+  if (isScalable && odsParser.parseRSquare().failed()) {
     odsParser.emitError(odsParser.getCurrentLocation(),
                         "missing closing `]` for scalable dim size");
     return {};
@@ -1575,19 +1578,19 @@ mlir::Type cir::VectorType::parse(::mlir::AsmParser 
&odsParser) {
   // Parse literal '>'
   if (odsParser.parseGreater())
     return {};
-  return odsParser.getChecked<VectorType>(odsLoc, odsParser.getContext(),
-                                          mlir::Type((*elementType)),
-                                          uint64_t((*size)), isScalabe);
+  return odsParser.getChecked<VectorType>(
+      odsLoc, odsParser.getContext(), mlir::Type((*elementType)),
+      llvm::ElementCount::get(*size, isScalable));
 }
 
 void cir::VectorType::print(mlir::AsmPrinter &odsPrinter) const {
   mlir::Builder odsBuilder(getContext());
   odsPrinter << "<";
-  if (this->getIsScalable())
+  if (getSize().isScalable())
     odsPrinter << "[";
 
-  odsPrinter.printStrippedAttrOrType(getSize());
-  if (this->getIsScalable())
+  odsPrinter.printStrippedAttrOrType(getSize().getKnownMinValue());
+  if (getSize().isScalable())
     odsPrinter << "]";
   odsPrinter << ' ' << "x";
   odsPrinter << ' ';
diff --git a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp 
b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
index 9d569be7b80cb0..72807f877bf143 100644
--- a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp
@@ -375,9 +375,10 @@ struct SimplifyVecSplat : public 
OpRewritePattern<VecSplatOp> {
     // we can simplify it here too.
     assert(!MissingFeatures::matrixType());
     auto resultType = 
mlir::dyn_cast<cir::VectorType>(op.getResult().getType());
-    if (!resultType)
+    if (!resultType || resultType.getSize().isScalable())
       return mlir::failure();
-    SmallVector<mlir::Attribute, 16> elements(resultType.getSize(), value);
+    SmallVector<mlir::Attribute, 16> elements(
+        resultType.getSize().getFixedValue(), value);
     auto constVecAttr = cir::ConstVectorAttr::get(
         resultType, mlir::ArrayAttr::get(getContext(), elements));
 
diff --git a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp 
b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
index e7632bdcb700d2..6f293dd8b408d4 100644
--- a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
+++ b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp
@@ -254,7 +254,7 @@ static bool isSupportedType(mlir::Type ty, const DataLayout 
&dl) {
   if (auto vecTy = dyn_cast<cir::VectorType>(ty)) {
     // A scalable vector has no size the SysV eightbyte rules can read, and
     // x86_64 has no calling convention for one.
-    if (vecTy.getIsScalable())
+    if (vecTy.getSize().isScalable())
       return false;
     // mapCIRType maps a bool as a one-bit integer, so a bool vector is sized
     // one bit per element, as clang packs it.  Vectors of a _BitInt whose
@@ -413,8 +413,8 @@ static mlir::Type unwrapLongDoubleVectorElement(mlir::Type 
ty) {
   if (auto vecTy = dyn_cast<cir::VectorType>(ty)) {
     if (auto longDoubleTy =
             dyn_cast<cir::LongDoubleType>(vecTy.getElementType()))
-      return cir::VectorType::get(longDoubleTy.getUnderlying(), 
vecTy.getSize(),
-                                  vecTy.getIsScalable());
+      return cir::VectorType::get(longDoubleTy.getUnderlying(),
+                                  vecTy.getSize());
   }
   return ty;
 }
@@ -472,8 +472,7 @@ static const llvm::abi::Type *mapCIRType(mlir::Type type,
         // always fixed here.
         return tb.getVectorType(
             mapCIRType(vecTy.getElementType(), typeMapper, dl, modOp),
-            llvm::ElementCount::getFixed(vecTy.getSize()),
-            llvm::Align(dl.getTypeABIAlignment(type)));
+            vecTy.getSize(), llvm::Align(dl.getTypeABIAlignment(type)));
       })
       .Case([&](cir::ArrayType arrTy) {
         const llvm::abi::Type *elemAbi =
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp 
b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 7b29331b762ad8..44a2f064eecff9 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -175,6 +175,8 @@ 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())) {
+      if (vecTy.getSize().isScalable())
+        return value;
       auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType());
       auto paddedVecTy =
           cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth());
@@ -183,7 +185,8 @@ static mlir::Value 
emitFromMemory(mlir::ConversionPatternRewriter &rewriter,
       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());
+      return emitBoolVecConversion(rewriter, v,
+                                   vecTy.getSize().getFixedValue());
     }
   }
 
@@ -218,9 +221,10 @@ static mlir::Value 
emitToMemory(mlir::ConversionPatternRewriter &rewriter,
   if (auto vecTy = mlir::dyn_cast<cir::VectorType>(origType)) {
     if (mlir::isa<cir::BoolType>(vecTy.getElementType())) {
       mlir::Type resultTy;
-      if (vecTy.getIsScalable())
-        resultTy = mlir::VectorType::get(
-            vecTy.getSize(), vecTy.getElementType(), vecTy.getIsScalable());
+      if (vecTy.getSize().isScalable())
+        resultTy = mlir::VectorType::get(vecTy.getSize().getKnownMinValue(),
+                                         vecTy.getElementType(),
+                                         vecTy.getSize().isScalable());
       else {
         resultTy = mlir::IntegerType::get(origType.getContext(),
                                           vecTy.getBoolStorageWidth());
@@ -3544,13 +3548,11 @@ mlir::LogicalResult 
CIRToLLVMNotOpLowering::matchAndRewrite(
   if (mlir::isa<cir::IntType>(elementType)) {
     mlir::Value minusOne;
     if (isVector) {
-      const uint64_t numElements =
-          mlir::cast<cir::VectorType>(op.getType()).getSize();
       const unsigned eltWidth =
           mlir::cast<cir::IntType>(elementType).getWidth();
-      SmallVector<APInt> values(numElements, APInt::getAllOnes(eltWidth));
-      mlir::DenseIntElementsAttr denseVec = mlir::DenseIntElementsAttr::get(
-          mlir::cast<mlir::ShapedType>(llvmType), values);
+      mlir::DenseElementsAttr denseVec =
+          mlir::DenseElementsAttr::get(mlir::cast<mlir::ShapedType>(llvmType),
+                                       {APInt::getAllOnes(eltWidth)});
       minusOne =
           mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
     } else {
@@ -3566,10 +3568,8 @@ mlir::LogicalResult 
CIRToLLVMNotOpLowering::matchAndRewrite(
   if (mlir::isa<cir::BoolType>(elementType)) {
     mlir::Value one;
     if (isVector) {
-      const uint64_t numElements =
-          mlir::cast<cir::VectorType>(op.getType()).getSize();
-      SmallVector<bool> values(numElements, true);
-      mlir::DenseIntElementsAttr denseVec = rewriter.getBoolVectorAttr(values);
+      mlir::DenseElementsAttr denseVec = mlir::DenseElementsAttr::get(
+          mlir::cast<mlir::ShapedType>(llvmType), {APInt(1, 1)});
       one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, denseVec);
     } else {
       one = mlir::LLVM::ConstantOp::create(rewriter, loc, llvmType, 1);
@@ -4194,7 +4194,8 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter 
&converter,
         intTy && intTy.isBitInt())
       return {};
     const mlir::Type ty = converter.convertType(type.getElementType());
-    return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
+    return mlir::VectorType::get(type.getSize().getKnownMinValue(), ty,
+                                 {type.getSize().isScalable()});
   });
   converter.addConversion([&](cir::MatrixType type) -> mlir::Type {
     const uint64_t size = type.getNumRows() * type.getNumColumns();
@@ -5225,10 +5226,11 @@ mlir::LogicalResult 
CIRToLLVMVecCreateOpLowering::matchAndRewrite(
   const mlir::Type llvmTy = typeConverter->convertType(vecTy);
   const mlir::Location loc = op.getLoc();
   mlir::Value result = mlir::LLVM::PoisonOp::create(rewriter, loc, llvmTy);
-  assert(vecTy.getSize() == op.getElements().size() &&
+  const uint64_t vectorSize = vecTy.getSize().getFixedValue();
+  assert(vectorSize == op.getElements().size() &&
          "cir.vec.create op count doesn't match vector type elements count");
 
-  for (uint64_t i = 0; i < vecTy.getSize(); ++i) {
+  for (uint64_t i = 0; i < vectorSize; ++i) {
     const mlir::Value indexValue =
         mlir::LLVM::ConstantOp::create(rewriter, loc, rewriter.getI64Type(), 
i);
     result = mlir::LLVM::InsertElementOp::create(
@@ -5320,8 +5322,9 @@ mlir::LogicalResult 
CIRToLLVMVecCmpOpLowering::matchAndRewrite(
         adaptor.getLhs(), adaptor.getRhs());
   } else if (mlir::isa<cir::FPTypeInterface>(elementType)) {
     if (cir::FenvAttr fenv = op.getFenvAttr()) {
-      auto i1VecTy = mlir::VectorType::get(op.getLhs().getType().getSize(),
-                                           rewriter.getI1Type());
+      llvm::ElementCount size = op.getLhs().getType().getSize();
+      auto i1VecTy = mlir::VectorType::get(
+          size.getKnownMinValue(), rewriter.getI1Type(), {size.isScalable()});
       bitResult = createConstrainedFCmpCall(rewriter, op.getLoc(),
                                             adaptor.getLhs(), adaptor.getRhs(),
                                             op.getKind(), fenv, i1VecTy)
@@ -5434,7 +5437,7 @@ mlir::LogicalResult 
CIRToLLVMVecShuffleDynamicOpLowering::matchAndRewrite(
       getTypeConverter()->convertType(op.getIndices().getType());
   mlir::Type llvmIndexType = getTypeConverter()->convertType(
       op.getIndices().getType().getElementType());
-  uint64_t numElements = op.getVec().getType().getSize();
+  uint64_t numElements = op.getVec().getType().getSize().getFixedValue();
 
   uint64_t maskBits = llvm::NextPowerOf2(numElements - 1) - 1;
   mlir::Value maskValue = mlir::LLVM::ConstantOp::create(
diff --git a/clang/test/CIR/IR/invalid-vector.cir 
b/clang/test/CIR/IR/invalid-vector.cir
index 6152ca4a7a9481..3af3d494c5fd55 100644
--- a/clang/test/CIR/IR/invalid-vector.cir
+++ b/clang/test/CIR/IR/invalid-vector.cir
@@ -11,6 +11,45 @@ cir.global external @vec_b = #cir.zero : !cir.vector<4 x 
!cir.array<!s32i x 10>>
 
 // -----
 
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.func @scalable_vector_constant() {
+    // expected-error @below {{scalable vector constants are not supported}}
+    %0 = cir.const #cir.const_vector<[#cir.int<1> : !s32i, #cir.int<2> : 
!s32i]> : !cir.vector<[2] x !s32i>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.func @scalable_vector_create() {
+    %0 = cir.const #cir.int<1> : !s32i
+    %1 = cir.const #cir.int<2> : !s32i
+    // expected-error @below {{scalable vectors are not supported}}
+    %2 = cir.vec.create(%0, %1 : !s32i, !s32i) : !cir.vector<[2] x !s32i>
+    cir.return
+  }
+}
+
+// -----
+
+!s32i = !cir.int<s, 32>
+
+module {
+  cir.func @scalable_vector_shuffle(%arg0: !cir.vector<[2] x !s32i>,
+                                    %arg1: !cir.vector<[2] x !s32i>) {
+    // expected-error @below {{scalable vectors are not supported}}
+    %0 = cir.vec.shuffle(%arg0, %arg1 : !cir.vector<[2] x !s32i>) [#cir.int<0> 
: !s32i, #cir.int<1> : !s32i] : !cir.vector<[2] x !s32i>
+    cir.return
+  }
+}
+
+// -----
+
 cir.func @invalid_scalable_vec_syntax() {
   // expected-error@+2 {{missing closing `]` for scalable dim size}}
   // expected-error @below {{expected ']'}}
diff --git a/clang/test/CIR/Lowering/not.cir b/clang/test/CIR/Lowering/not.cir
index d93f33cd84ba4b..adf8431ccd4278 100644
--- a/clang/test/CIR/Lowering/not.cir
+++ b/clang/test/CIR/Lowering/not.cir
@@ -2,6 +2,7 @@
 // RUN: cir-translate %s -cir-to-llvmir --target x86_64-unknown-linux-gnu 
--disable-cc-lowering  | FileCheck %s -check-prefix=LLVM
 
 !s128i = !cir.int<s, 128>
+!s32i = !cir.int<s, 32>
 !u128i = !cir.int<u, 128>
 
 module attributes { cir.triple = "x86_64-unknown-linux-gnu" } {
@@ -30,4 +31,17 @@ cir.func @unsigned(%arg: !u128i) -> !u128i {
 // LLVM: define i128 @unsigned(i128 %[[ARG:.*]])
 // LLVM: %[[INVERT:.*]] = xor i128 %[[ARG]], -1 
 // LLVM: ret i128 %[[INVERT]]
+
+cir.func @scalable_vector(%arg: !cir.vector<[4] x !s32i>) -> !cir.vector<[4] x 
!s32i> {
+  %inverted = cir.not %arg : !cir.vector<[4] x !s32i>
+  cir.return %inverted : !cir.vector<[4] x !s32i>
+}
+// MLIR: llvm.func @scalable_vector(%[[ARG:.*]]: vector<[4]xi32>) -> 
vector<[4]xi32>
+// MLIR: %[[NEG_ONE:.*]] = llvm.mlir.constant(dense<-1> : vector<[4]xi32>) : 
vector<[4]xi32>
+// MLIR: %[[INVERT:.*]] = llvm.xor %[[ARG]], %[[NEG_ONE]] : vector<[4]xi32>
+// MLIR: llvm.return %[[INVERT]] : vector<[4]xi32>
+
+// LLVM: define <vscale x 4 x i32> @scalable_vector(<vscale x 4 x i32> 
%[[ARG:.*]])
+// LLVM: %[[INVERT:.*]] = xor <vscale x 4 x i32> %[[ARG]], splat (i32 -1)
+// LLVM: ret <vscale x 4 x i32> %[[INVERT]]
 }
diff --git a/clang/test/CIR/Transforms/vector-splat.cir 
b/clang/test/CIR/Transforms/vector-splat.cir
index 9b2b39d7f862e3..d444e2143d95dc 100644
--- a/clang/test/CIR/Transforms/vector-splat.cir
+++ b/clang/test/CIR/Transforms/vector-splat.cir
@@ -13,4 +13,15 @@ module  {
   // CHECK-NEXT: %0 = cir.const #cir.const_vector<[#cir.int<3> : !s32i, 
#cir.int<3> : !s32i,
   // CHECK-SAME: #cir.int<3> : !s32i, #cir.int<3> : !s32i]> : !cir.vector<4 x 
!s32i>
   // CHECK-NEXT: cir.return %0 : !cir.vector<4 x !s32i>
+
+  cir.func @do_not_fold_scalable_splat() -> !cir.vector<[4] x !s32i> {
+    %v = cir.const #cir.int<3> : !s32i
+    %vec = cir.vec.splat %v : !s32i, !cir.vector<[4] x !s32i>
+    cir.return %vec : !cir.vector<[4] x !s32i>
+  }
+
+  // CHECK-LABEL: cir.func @do_not_fold_scalable_splat
+  // CHECK: %[[VALUE:.*]] = cir.const #cir.int<3> : !s32i
+  // CHECK-NEXT: %[[VEC:.*]] = cir.vec.splat %[[VALUE]] : !s32i, 
!cir.vector<[4] x !s32i>
+  // CHECK-NEXT: cir.return %[[VEC]] : !cir.vector<[4] x !s32i>
 }
diff --git a/llvm/include/llvm/Support/TypeSize.h 
b/llvm/include/llvm/Support/TypeSize.h
index 5a34c7daeb02f5..b9db5d5205dcd0 100644
--- a/llvm/include/llvm/Support/TypeSize.h
+++ b/llvm/include/llvm/Support/TypeSize.h
@@ -15,6 +15,7 @@
 #ifndef LLVM_SUPPORT_TYPESIZE_H
 #define LLVM_SUPPORT_TYPESIZE_H
 
+#include "llvm/ADT/Hashing.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/MathExtras.h"
@@ -322,6 +323,10 @@ class ElementCount
   }
 };
 
+inline hash_code hash_value(const ElementCount &EC) {
+  return hash_combine(EC.getKnownMinValue(), EC.isScalable());
+}
+
 // Stores the size of a type. If the type is of fixed size, it will represent
 // the exact size. If the type is a scalable vector, it will represent the 
known
 // minimum size.

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

Reply via email to