Author: Benjamin Maxwell Date: 2026-10-22T10:18:09+01:00 New Revision: 1a12b033bc0e525695319bfa0d96e77b844305ad
URL: https://github.com/llvm/llvm-project/commit/1a12b033bc0e525695319bfa0d96e77b844305ad DIFF: https://github.com/llvm/llvm-project/commit/1a12b033bc0e525695319bfa0d96e77b844305ad.diff LOG: [CIR] Use `llvm::ElementCount` to hold `cir::VectorType` size (#231906) A separate scalability flag is a design issue inherited from MLIR's VectorType. 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 Added: Modified: clang/include/clang/CIR/Dialect/IR/CIROps.td clang/include/clang/CIR/Dialect/IR/CIRTypes.h clang/include/clang/CIR/Dialect/IR/CIRTypes.td clang/lib/CIR/CodeGen/CIRGenBuilder.h clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp clang/lib/CIR/CodeGen/CIRGenExpr.cpp clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp clang/lib/CIR/CodeGen/CIRGenTypes.cpp clang/lib/CIR/Dialect/IR/CIRAttrs.cpp clang/lib/CIR/Dialect/IR/CIRDataLayout.cpp clang/lib/CIR/Dialect/IR/CIRDialect.cpp clang/lib/CIR/Dialect/IR/CIRTypes.cpp clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp clang/test/CIR/IR/invalid-vector.cir clang/test/CIR/Lowering/not.cir clang/test/CIR/Transforms/vector-splat.cir clang/unittests/CIR/PointerLikeTest.cpp clang/unittests/CIR/VectorTypeABIAlignTest.cpp llvm/include/llvm/Support/TypeSize.h Removed: ################################################################################ diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 4dde0a667ac5a1..a56ed5141322eb 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -6708,7 +6708,7 @@ def CIR_MatrixExtractRowOp : CIR_Op<"matrix.extract_row", [ "type of 'result' matches vector type with same element type of 'matrix' " "and size equals to num columns", "matrix", "result", - "cir::VectorType::get(" + "cir::VectorType::getFixed(" "mlir::cast<cir::MatrixType>($_self).getElementType()," "mlir::cast<cir::MatrixType>($_self).getNumColumns()" ")"> 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..2534f110b71d5c 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,20 +525,34 @@ 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); }]>, ]; let extraClassDeclaration = [{ + /// Return the size of a fixed-width vector. + uint64_t getFixedSize() const { return getSize().getFixedValue(); } + + /// Return whether this vector is scalable. + bool isScalable() const { return getSize().isScalable(); } + + /// Return a fixed-width vector with the given element type and size. + static VectorType getFixed(mlir::Type elementType, uint64_t size) { + return get(elementType, llvm::ElementCount::getFixed(size)); + } + + /// Return a scalable vector with the given element type and minimum size. + static VectorType getScalable(mlir::Type elementType, uint64_t size) { + return get(elementType, llvm::ElementCount::getScalable(size)); + } + /// The width of the integer a vector of `!cir.bool` is stored as: one bit /// per element, at least a byte. uint64_t getBoolStorageWidth() const; diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h index b9cc67e394accf..e60e3092b699f3 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h @@ -803,7 +803,7 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy { llvm::ArrayRef<mlir::Attribute> maskAttrs) { auto vecType = mlir::cast<cir::VectorType>(vec1.getType()); auto resultTy = - cir::VectorType::get(vecType.getElementType(), maskAttrs.size()); + cir::VectorType::getFixed(vecType.getElementType(), maskAttrs.size()); return cir::VecShuffleOp::create(*this, loc, resultTy, vec1, vec2, getArrayAttr(maskAttrs)); } diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp index a94139cff20ffb..21a86114420e19 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltin.cpp @@ -1174,7 +1174,7 @@ decodeFixedType(CIRGenFunction &cgf, case IITDescriptor::Vector: { mlir::Type elementType = decodeFixedType(cgf, infos, overloadTys, context); unsigned numElements = descriptor.VectorWidth.getFixedValue(); - return cir::VectorType::get(elementType, numElements); + return cir::VectorType::getFixed(elementType, numElements); } case IITDescriptor::Pointer: { mlir::Builder builder(context); diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp index 30438d5288608a..1dbb6c2c3defc8 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp @@ -96,11 +96,11 @@ static cir::VectorType getFloatNeonType(CIRGenFunction &cgf, int isQuad = intTypeFlags.isQuad(); switch (intTypeFlags.getEltType()) { case NeonTypeFlags::Int16: - return cir::VectorType::get(cgf.fP16Ty, (4 << isQuad)); + return cir::VectorType::getFixed(cgf.fP16Ty, (4 << isQuad)); case NeonTypeFlags::Int32: - return cir::VectorType::get(cgf.floatTy, (2 << isQuad)); + return cir::VectorType::getFixed(cgf.floatTy, (2 << isQuad)); case NeonTypeFlags::Int64: - return cir::VectorType::get(cgf.doubleTy, (1 << isQuad)); + return cir::VectorType::getFixed(cgf.doubleTy, (1 << isQuad)); default: llvm_unreachable("Type can't be converted to floating-point!"); } @@ -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.getFixedSize(); auto intTy = mlir::dyn_cast<cir::IntType>(elemTy); assert(intTy && "vpaddl result type must be an integer vector"); @@ -220,7 +220,7 @@ static cir::VectorType getNeonPairwiseWidenInputType(cir::VectorType resType, unsigned argWidth = resWidth / 2; unsigned argLanes = resLanes * 2; - cir::VectorType result = cir::VectorType::get( + cir::VectorType result = cir::VectorType::getFixed( cir::IntType::get(resType.getContext(), argWidth, /* is_signed */ !usgn), argLanes); return result; @@ -256,7 +256,7 @@ deriveNeonSISDIntrinsicOperandTypes(CIRGenFunction &cgf, unsigned modifier, auto wrapAsVector = [&](mlir::Type ty) -> cir::VectorType { unsigned bits = cgf.cgm.getDataLayout().getTypeSizeInBits(ty); unsigned elts = vectorSize ? vectorSize / bits : 1; - return cir::VectorType::get(ty, elts); + return cir::VectorType::getFixed(ty, elts); }; // Determine the vectorized data type. @@ -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).isScalable() && "This is only intended for fixed-width vectors"); // Vector types are cast to i8 vectors. Recover original type. src = builder.createBitcast(src, retTy); @@ -661,46 +661,46 @@ static cir::VectorType getNeonType(CIRGenFunction *cgf, NeonTypeFlags typeFlags, switch (typeFlags.getEltType()) { case NeonTypeFlags::Int8: case NeonTypeFlags::Poly8: - return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt8Ty - : cgf->sInt8Ty, - v1Ty ? 1 : (8 << isQuad)); + return cir::VectorType::getFixed(typeFlags.isUnsigned() ? cgf->uInt8Ty + : cgf->sInt8Ty, + v1Ty ? 1 : (8 << isQuad)); case NeonTypeFlags::MFloat8: - return cir::VectorType::get(cgf->uInt8Ty, v1Ty ? 1 : (8 << isQuad)); + return cir::VectorType::getFixed(cgf->uInt8Ty, v1Ty ? 1 : (8 << isQuad)); case NeonTypeFlags::Int16: case NeonTypeFlags::Poly16: - return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt16Ty - : cgf->sInt16Ty, - v1Ty ? 1 : (4 << isQuad)); + return cir::VectorType::getFixed(typeFlags.isUnsigned() ? cgf->uInt16Ty + : cgf->sInt16Ty, + v1Ty ? 1 : (4 << isQuad)); case NeonTypeFlags::BFloat16: if (allowBFloatArgsAndRet) - return cir::VectorType::get(cgf->getCIRGenModule().bFloat16Ty, - v1Ty ? 1 : (4 << isQuad)); - return cir::VectorType::get(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad)); + return cir::VectorType::getFixed(cgf->getCIRGenModule().bFloat16Ty, + v1Ty ? 1 : (4 << isQuad)); + return cir::VectorType::getFixed(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad)); case NeonTypeFlags::Float16: if (hasLegalHalfType) - return cir::VectorType::get(cgf->getCIRGenModule().fP16Ty, - v1Ty ? 1 : (4 << isQuad)); - return cir::VectorType::get(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad)); + return cir::VectorType::getFixed(cgf->getCIRGenModule().fP16Ty, + v1Ty ? 1 : (4 << isQuad)); + return cir::VectorType::getFixed(cgf->uInt16Ty, v1Ty ? 1 : (4 << isQuad)); case NeonTypeFlags::Int32: - return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt32Ty - : cgf->sInt32Ty, - v1Ty ? 1 : (2 << isQuad)); + return cir::VectorType::getFixed(typeFlags.isUnsigned() ? cgf->uInt32Ty + : cgf->sInt32Ty, + v1Ty ? 1 : (2 << isQuad)); case NeonTypeFlags::Int64: case NeonTypeFlags::Poly64: - return cir::VectorType::get(typeFlags.isUnsigned() ? cgf->uInt64Ty - : cgf->sInt64Ty, - v1Ty ? 1 : (1 << isQuad)); + return cir::VectorType::getFixed(typeFlags.isUnsigned() ? cgf->uInt64Ty + : cgf->sInt64Ty, + v1Ty ? 1 : (1 << isQuad)); case NeonTypeFlags::Poly128: // FIXME: i128 and f128 doesn't get fully support in Clang and llvm. // There is a lot of i128 and f128 API missing. // so we use v16i8 to represent poly128 and get pattern matched. - return cir::VectorType::get(cgf->uInt8Ty, 16); + return cir::VectorType::getFixed(cgf->uInt8Ty, 16); case NeonTypeFlags::Float32: - return cir::VectorType::get(cgf->getCIRGenModule().floatTy, - v1Ty ? 1 : (2 << isQuad)); + return cir::VectorType::getFixed(cgf->getCIRGenModule().floatTy, + v1Ty ? 1 : (2 << isQuad)); case NeonTypeFlags::Float64: - return cir::VectorType::get(cgf->getCIRGenModule().doubleTy, - v1Ty ? 1 : (1 << isQuad)); + return cir::VectorType::getFixed(cgf->getCIRGenModule().doubleTy, + v1Ty ? 1 : (1 << isQuad)); } llvm_unreachable("Unknown vector element type!"); } @@ -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.getFixedSize(); if (builtinID == NEON::BI__builtin_neon_splatq_lane_v) numElements *= 2; if (builtinID == NEON::BI__builtin_neon_splat_laneq_v) @@ -926,7 +926,7 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vaddq_v: { unsigned numBytes = (builtinID == NEON::BI__builtin_neon_vaddq_v) ? 16 : 8; cir::VectorType byteTy = - cir::VectorType::get(cgf.getBuilder().getUInt8Ty(), numBytes); + cir::VectorType::getFixed(cgf.getBuilder().getUInt8Ty(), numBytes); ops[0] = cgf.getBuilder().createBitcast(ops[0], byteTy); ops[1] = cgf.getBuilder().createBitcast(ops[1], byteTy); mlir::Value result = cgf.getBuilder().createXor(loc, ops[0], ops[1]); @@ -1144,8 +1144,8 @@ static mlir::Value emitCommonNeonBuiltinExpr( case NEON::BI__builtin_neon_vcvtx_f32_v: { llvm::StringRef llvmIntrName = getLLVMIntrNameNoPrefix( static_cast<llvm::Intrinsic::ID>(llvmIntrinsic)); - auto v2f64 = cir::VectorType::get(cgf.cgm.doubleTy, 2); - auto v2f32 = cir::VectorType::get(cgf.cgm.floatTy, 2); + auto v2f64 = cir::VectorType::getFixed(cgf.cgm.doubleTy, 2); + auto v2f32 = cir::VectorType::getFixed(cgf.cgm.floatTy, 2); return emitNeonCall(cgf.getCIRGenModule(), cgf.getBuilder(), /*argTypes=*/{v2f64}, ops, llvmIntrName, /*funcResTy=*/v2f32, loc); @@ -1511,8 +1511,7 @@ 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::getScalable(builder.getUIntNTy(1), minNumElts); if (pred.getType() == retTy) return pred; @@ -1585,33 +1584,33 @@ 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::getScalable(builder.getUInt8Ty(), 16); case SVETypeFlags::EltTyInt16: - return cir::VectorType::get(builder.getUInt16Ty(), 8, true); + return cir::VectorType::getScalable(builder.getUInt16Ty(), 8); case SVETypeFlags::EltTyInt32: - return cir::VectorType::get(builder.getUInt32Ty(), 4, true); + return cir::VectorType::getScalable(builder.getUInt32Ty(), 4); case SVETypeFlags::EltTyInt64: - return cir::VectorType::get(builder.getUInt64Ty(), 2, true); + return cir::VectorType::getScalable(builder.getUInt64Ty(), 2); case SVETypeFlags::EltTyMFloat8: - return cir::VectorType::get(builder.getUInt8Ty(), 16, true); + return cir::VectorType::getScalable(builder.getUInt8Ty(), 16); case SVETypeFlags::EltTyFloat16: - return cir::VectorType::get(builder.getFp16Ty(), 8, true); + return cir::VectorType::getScalable(builder.getFp16Ty(), 8); case SVETypeFlags::EltTyBFloat16: - return cir::VectorType::get(builder.getBF16Type(), 8, true); + return cir::VectorType::getScalable(builder.getBF16Type(), 8); case SVETypeFlags::EltTyFloat32: - return cir::VectorType::get(builder.getF32Type(), 4, true); + return cir::VectorType::getScalable(builder.getF32Type(), 4); case SVETypeFlags::EltTyFloat64: - return cir::VectorType::get(builder.getDoubleTy(), 2, true); + return cir::VectorType::getScalable(builder.getDoubleTy(), 2); case SVETypeFlags::EltTyBool8: - return cir::VectorType::get(builder.getUIntNTy(1), 16, true); + return cir::VectorType::getScalable(builder.getUIntNTy(1), 16); case SVETypeFlags::EltTyBool16: - return cir::VectorType::get(builder.getUIntNTy(1), 8, true); + return cir::VectorType::getScalable(builder.getUIntNTy(1), 8); case SVETypeFlags::EltTyBool32: - return cir::VectorType::get(builder.getUIntNTy(1), 4, true); + return cir::VectorType::getScalable(builder.getUIntNTy(1), 4); case SVETypeFlags::EltTyBool64: - return cir::VectorType::get(builder.getUIntNTy(1), 2, true); + return cir::VectorType::getScalable(builder.getUIntNTy(1), 2); } } @@ -1622,7 +1621,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::getScalable(eltTy, numElts); } //===----------------------------------------------------------------------===// @@ -2815,7 +2814,8 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, std::nullopt, halfTy, loc); } case NEON::BI__builtin_neon_vaddq_p128: { - cir::VectorType byteTy = cir::VectorType::get(builder.getUInt8Ty(), 16); + cir::VectorType byteTy = + cir::VectorType::getFixed(builder.getUInt8Ty(), 16); ops[0] = builder.createBitcast(ops[0], byteTy); ops[1] = builder.createBitcast(ops[1], byteTy); mlir::Value result = builder.createXor(loc, ops[0], ops[1]); @@ -3147,14 +3147,14 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, getContext().BuiltinInfo.getName(builtinID)); return mlir::Value{}; case NEON::BI__builtin_neon_vcvt_f16_f32: { - auto v4f32 = cir::VectorType::get(cgm.floatTy, 4); - auto v4f16 = cir::VectorType::get(cgm.fP16Ty, 4); + auto v4f32 = cir::VectorType::getFixed(cgm.floatTy, 4); + auto v4f16 = cir::VectorType::getFixed(cgm.fP16Ty, 4); return builder.createFloatingCast(builder.createBitcast(ops[0], v4f32), v4f16); } case NEON::BI__builtin_neon_vcvt_f32_f16: { - auto v4f32 = cir::VectorType::get(cgm.floatTy, 4); - auto v4f16 = cir::VectorType::get(cgm.fP16Ty, 4); + auto v4f32 = cir::VectorType::getFixed(cgm.floatTy, 4); + auto v4f16 = cir::VectorType::getFixed(cgm.fP16Ty, 4); return builder.createFloatingCast(builder.createBitcast(ops[0], v4f16), v4f32); } @@ -3201,12 +3201,13 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, // For vfmaq_lane, the lane source operand is the non-quad vector, so it has // half as many lanes as the quad result vector. For vfma_lane, it has the // same shape as the result vector. - cir::VectorType sourceTy = cir::VectorType::get( + cir::VectorType sourceTy = cir::VectorType::getFixed( ty.getElementType(), builtinID == NEON::BI__builtin_neon_vfmaq_lane_v - ? ty.getSize() / 2 - : ty.getSize()); + ? ty.getFixedSize() / 2 + : ty.getFixedSize()); 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.getFixedSize()); llvm::SmallVector<mlir::Value> fmaOps = {multiplicand, laneSource, addend}; return emitNeonCallToOp<cir::FMAOp>(cgm, builder, {ty, ty, ty}, fmaOps, @@ -3219,7 +3220,7 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, mlir::Value multiplicand = builder.createBitcast(ops[1], cgm.doubleTy); // The laneq source operand is float64x2_t, so the source vector has two // double lanes. - cir::VectorType sourceTy = cir::VectorType::get(cgm.doubleTy, 2); + cir::VectorType sourceTy = cir::VectorType::getFixed(cgm.doubleTy, 2); mlir::Value laneSource = builder.createBitcast(ops[2], sourceTy); laneSource = builder.createExtractElement( loc, laneSource, @@ -3239,9 +3240,10 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, // The laneq source operand is the quad vector, so it has twice as many // lanes as the non-quad result vector. cir::VectorType sourceTy = - cir::VectorType::get(ty.getElementType(), ty.getSize() * 2); + cir::VectorType::getFixed(ty.getElementType(), ty.getFixedSize() * 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.getFixedSize()); llvm::SmallVector<mlir::Value> fmaOps = {laneSource, multiplicand, addend}; return emitNeonCallToOp<cir::FMAOp>(cgm, builder, {ty, ty, ty}, fmaOps, @@ -3251,7 +3253,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.getFixedSize()); llvm::SmallVector<mlir::Value> fmaOps = {laneSource, multiplicand, addend}; return emitNeonCallToOp<cir::FMAOp>(cgm, builder, {ty, ty, ty}, fmaOps, @@ -3482,14 +3485,14 @@ CIRGenFunction::emitAArch64BuiltinExpr(unsigned builtinID, const CallExpr *expr, this, NeonTypeFlags(NeonTypeFlags::Float64, false, type.isQuad())); return builder.createCast(loc, cir::CastKind::int_to_float, ops[0], ty); case NEON::BI__builtin_neon_vcvt_f64_f32: { - auto v2f32 = cir::VectorType::get(cgm.floatTy, 2); - auto v2f64 = cir::VectorType::get(cgm.doubleTy, 2); + auto v2f32 = cir::VectorType::getFixed(cgm.floatTy, 2); + auto v2f64 = cir::VectorType::getFixed(cgm.doubleTy, 2); return builder.createFloatingCast(builder.createBitcast(ops[0], v2f32), v2f64); } case NEON::BI__builtin_neon_vcvt_f32_f64: { - auto v2f32 = cir::VectorType::get(cgm.floatTy, 2); - auto v2f64 = cir::VectorType::get(cgm.doubleTy, 2); + auto v2f32 = cir::VectorType::getFixed(cgm.floatTy, 2); + auto v2f64 = cir::VectorType::getFixed(cgm.doubleTy, 2); return builder.createFloatingCast(builder.createBitcast(ops[0], v2f64), v2f32); } @@ -3843,7 +3846,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.getFixedSize(); i != e; i += 2) { indices.push_back(i + vi); indices.push_back(i + e + vi); } @@ -3864,7 +3867,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.getFixedSize(); i != e; ++i) { indices.push_back(2 * i + vi); } cir::ConstantOp idx = builder.getConstInt(loc, builder.getSInt32Ty(), vi); @@ -3884,7 +3887,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.getFixedSize(); 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 c4bd6b687c8f57..35d1b67563df62 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinX86.cpp @@ -69,7 +69,7 @@ static mlir::Value emitVectorFCmp(CIRGenFunction &cgf, const CallExpr &expr, static mlir::Value getMaskVecValue(CIRGenBuilderTy &builder, mlir::Location loc, mlir::Value mask, unsigned numElems) { - auto maskTy = cir::VectorType::get( + auto maskTy = cir::VectorType::getFixed( builder.getSIntNTy(1), cast<cir::IntType>(mask.getType()).getWidth()); mlir::Value maskVec = builder.createBitcast(mask, maskTy); @@ -184,7 +184,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.getFixedSize()); return builder.emitIntrinsicCallOp( loc, "masked.compressstore", cir::VoidType::get(builder.getContext()), @@ -206,7 +206,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.getFixedSize(); unsigned firstHalfStart = isLow ? 0 : 4; unsigned secondHalfStart = 4 - firstHalfStart; @@ -234,7 +234,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.getFixedSize(); unsigned numLanes = cgf.cgm.getDataLayout().getTypeSizeInBits(vecTy) / 128; unsigned numLaneElts = numElts / numLanes; @@ -286,8 +286,9 @@ static mlir::Value emitX86CompressExpand(CIRGenBuilderTy &builder, mlir::Value inputVector, const std::string &id) { auto resultTy = cast<cir::VectorType>(mask.getType()); - mlir::Value maskValue = getMaskVecValue( - builder, loc, inputVector, cast<cir::VectorType>(resultTy).getSize()); + mlir::Value maskValue = + getMaskVecValue(builder, loc, inputVector, + cast<cir::VectorType>(resultTy).getFixedSize()); return builder.emitIntrinsicCallOp(loc, id, resultTy, mlir::ValueRange{source, mask, maskValue}); } @@ -297,7 +298,8 @@ emitEncodeKey(mlir::MLIRContext *context, CIRGenBuilderTy &builder, const mlir::Location &location, mlir::ValueRange inputOperands, mlir::Value outputOperand, std::uint8_t vecOutputCount, const std::string &intrinsicName, std::uint8_t numResults) { - cir::VectorType resVector = cir::VectorType::get(builder.getUInt64Ty(), 2); + cir::VectorType resVector = + cir::VectorType::getFixed(builder.getUInt64Ty(), 2); llvm::SmallVector<mlir::Type> members{builder.getUInt32Ty()}; llvm::append_range(members, llvm::SmallVector<mlir::Type>(vecOutputCount, resVector)); @@ -328,7 +330,7 @@ static mlir::Value emitX86Select(CIRGenBuilderTy &builder, mlir::Location loc, return op0; mask = getMaskVecValue(builder, loc, mask, - cast<cir::VectorType>(op0.getType()).getSize()); + cast<cir::VectorType>(op0.getType()).getFixedSize()); return cir::VecTernaryOp::create(builder, loc, mask, op0, op1); } @@ -341,7 +343,7 @@ static mlir::Value getMaskZeroBitAsBool(CIRGenBuilderTy &builder, assert(intTy && "mask must be an integer type"); unsigned width = intTy.getWidth(); - auto maskVecTy = cir::VectorType::get(builder.getSIntNTy(1), width); + auto maskVecTy = cir::VectorType::getFixed(builder.getSIntNTy(1), width); mlir::Value maskVec = builder.createBitcast(mask, maskVecTy); // Extract bit 0 from the mask vector @@ -478,14 +480,14 @@ 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()).getFixedSize(); mlir::Value cmp; if (cc == 3) { cmp = builder.getNullValue( - cir::VectorType::get(builder.getSIntNTy(1), numElts), loc); + cir::VectorType::getFixed(builder.getSIntNTy(1), numElts), loc); } else if (cc == 7) { cir::VectorType resultTy = - cir::VectorType::get(builder.getSIntNTy(1), numElts); + cir::VectorType::getFixed(builder.getSIntNTy(1), numElts); llvm::APInt allOnes = llvm::APInt::getAllOnes(1); cmp = cir::VecSplatOp::create( builder, loc, resultTy, @@ -515,7 +517,7 @@ emitX86MaskedCompare(CIRGenBuilderTy &builder, unsigned cc, bool isSigned, break; } - auto resultTy = cir::VectorType::get(builder.getSIntNTy(1), numElts); + auto resultTy = cir::VectorType::getFixed(builder.getSIntNTy(1), numElts); cmp = cir::VecCmpOp::create(builder, loc, resultTy, pred, ops[0], ops[1]); } @@ -540,7 +542,7 @@ 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).getFixedSize(); mlir::Value mask = getMaskVecValue(builder, loc, op, numberOfElements); return builder.createCast(loc, cir::CastKind::integral, mask, dstTy); @@ -549,7 +551,7 @@ 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()).getFixedSize(); uint64_t index = indexOp.getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue(); @@ -572,7 +574,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.getFixedSize(); auto amtTy = mlir::cast<cir::IntType>(amt.getType()); auto vecElemTy = mlir::cast<cir::IntType>(vecTy.getElementType()); @@ -586,8 +588,8 @@ static mlir::Value emitX86FunnelShift(CIRGenBuilderTy &builder, cir::IntType unsignedVecElemType = builder.getUIntNTy(vecElemTy.getWidth()); amt = builder.createIntCast(amt, unsignedVecElemType); amt = cir::VecSplatOp::create( - builder, location, cir::VectorType::get(unsignedVecElemType, numElems), - amt); + builder, location, + cir::VectorType::getFixed(unsignedVecElemType, numElems), amt); } const StringRef intrinsicName = isRight ? "fshr" : "fshl"; @@ -599,8 +601,8 @@ static mlir::Value emitX86Muldq(CIRGenBuilderTy &builder, mlir::Location loc, bool isSigned, SmallVectorImpl<mlir::Value> &ops, unsigned opTypePrimitiveSizeInBits) { - mlir::Type ty = cir::VectorType::get(builder.getSInt64Ty(), - opTypePrimitiveSizeInBits / 64); + mlir::Type ty = cir::VectorType::getFixed(builder.getSInt64Ty(), + opTypePrimitiveSizeInBits / 64); mlir::Value lhs = builder.createBitcast(loc, ops[0], ty); mlir::Value rhs = builder.createBitcast(loc, ops[1], ty); if (isSigned) { @@ -647,18 +649,18 @@ static mlir::Value emitX86CvtF16ToFloatExpr(CIRGenBuilderTy &builder, } } - unsigned numElts = cast<cir::VectorType>(dstTy).getSize(); + unsigned numElts = cast<cir::VectorType>(dstTy).getFixedSize(); mlir::Value src = ops[0]; // Extract the subvector - if (numElts != cast<cir::VectorType>(src.getType()).getSize()) { + if (numElts != cast<cir::VectorType>(src.getType()).getFixedSize()) { assert(numElts == 4 && "Unexpected vector size"); src = builder.createVecShuffle(loc, src, {0, 1, 2, 3}); } // Bitcast from vXi16 to vXf16. - cir::VectorType halfTy = - cir::VectorType::get(cir::FP16Type::get(builder.getContext()), numElts); + cir::VectorType halfTy = cir::VectorType::getFixed( + cir::FP16Type::get(builder.getContext()), numElts); src = builder.createCast(cir::CastKind::bitcast, src, halfTy); @@ -728,7 +730,7 @@ 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()).getFixedSize(); mlir::Value maskIn = ops[2]; ops.erase(ops.begin() + 2); @@ -774,7 +776,7 @@ static mlir::Value emitX86Fpclass(CIRGenBuilderTy &builder, mlir::Location loc, break; } - auto cmpResultTy = cir::VectorType::get(builder.getSIntNTy(1), numElts); + auto cmpResultTy = cir::VectorType::getFixed(builder.getSIntNTy(1), numElts); mlir::Value fpclass = builder.emitIntrinsicCallOp(loc, intrinsicName, cmpResultTy, ops); return emitX86MaskedCompareResult(builder, fpclass, numElts, maskIn, loc); @@ -903,8 +905,8 @@ 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).getFixedSize()); return builder.createMaskedLoad(loc, ty, ptr, alignment, maskVec, ops[1]); } @@ -913,7 +915,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.isScalable() && "This is only intended for fixed-width vectors"); const uint8_t imm = CIRGenFunction::getZExtIntValueFromConstOp(ops[2]); @@ -927,7 +929,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.getFixedSize(); // We must evaluated each lane(128 bits) separetely for (auto lane : llvm::seq(0, 2)) { bool isZeroBit = imm & (1 << ((lane * 4) + 3)), @@ -958,7 +960,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.isScalable() && "This is only intended for fixed-width vectors"); unsigned shiftVal = CIRGenFunction::getZExtIntValueFromConstOp(ops[1]) & 0xFF; @@ -970,7 +972,7 @@ static mlir::Value emitX86PackedByteShift(CIRGenBuilderTy &builder, if (shiftVal >= 16) return zeroVector; - uint64_t numElts = byteVecType.getSize(); + uint64_t numElts = byteVecType.getFixedSize(); assert(numElts % 16 == 0 && "Expected a multiple of 16"); llvm::SmallVector<int64_t, 64> shuffleMask; @@ -1285,7 +1287,7 @@ 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()).getFixedSize(); uint64_t index = getZExtIntValueFromConstOp(ops[1]); index &= numElts - 1; @@ -1774,8 +1776,8 @@ 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()); + std::min(cast<cir::VectorType>(ops[0].getType()).getFixedSize(), + cast<cir::VectorType>(ops[2].getType()).getFixedSize()); ops[3] = getMaskVecValue(builder, loc, ops[3], minElts); return builder.emitIntrinsicCallOp(loc, intrinsicName, convertType(expr->getType()), ops); @@ -1884,8 +1886,8 @@ 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()); + std::min(cast<cir::VectorType>(ops[2].getType()).getFixedSize(), + cast<cir::VectorType>(ops[3].getType()).getFixedSize()); ops[1] = getMaskVecValue(builder, loc, ops[1], minElts); return builder.emitIntrinsicCallOp(loc, intrinsicName, @@ -1909,8 +1911,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.getFixedSize(); + unsigned srcNumElts = + cast<cir::VectorType>(ops[0].getType()).getFixedSize(); unsigned subVectors = srcNumElts / numElts; assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 subvectors"); unsigned index = @@ -1947,8 +1950,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()).getFixedSize(); + unsigned srcNumElts = + cast<cir::VectorType>(ops[1].getType()).getFixedSize(); unsigned subVectors = dstNumElts / srcNumElts; assert(llvm::isPowerOf2_32(subVectors) && "Expected power of 2 subvectors"); assert(dstNumElts <= 16); @@ -1990,7 +1995,7 @@ 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()).getFixedSize(); llvm::SmallVector<mlir::Attribute, 16> indices; // If there are more than 8 elements, the immediate is used twice so make @@ -2049,7 +2054,7 @@ 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()).getFixedSize(); // These intrinsics operate on 256-bit lanes of four 64-bit elements. int64_t Indices[8]; @@ -2066,7 +2071,7 @@ 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()).getFixedSize(); assert(numElts % 16 == 0); // If palignr is shifting the pair of vectors more than the size of two @@ -2104,7 +2109,7 @@ 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()).getFixedSize(); unsigned shiftVal = ops[2].getDefiningOp<cir::ConstantOp>().getIntValue().getZExtValue() & 0xff; @@ -2134,7 +2139,7 @@ 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()).getFixedSize(); unsigned totalBits = getContext().getTypeSize(expr->getArg(0)->getType()); unsigned numLanes = totalBits == 512 ? 4 : 2; unsigned numElemsPerLane = numElems / numLanes; @@ -2656,7 +2661,7 @@ 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()).getFixedSize(); mlir::Location loc = getLoc(expr->getExprLoc()); StringRef intrinsicName; @@ -2683,7 +2688,7 @@ CIRGenFunction::emitX86BuiltinExpr(unsigned builtinID, const CallExpr *expr) { break; } - auto resVector = cir::VectorType::get(builder.getSIntNTy(1), numElts); + auto resVector = cir::VectorType::getFixed(builder.getSIntNTy(1), numElts); mlir::Type resMembers[] = {resVector, resVector}; cir::StructType resRecord = cir::StructType::get( @@ -2797,7 +2802,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.getFixedSize(); 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 dfd6fa725e77fe..a8181c8c6a5b40 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExpr.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExpr.cpp @@ -351,7 +351,7 @@ 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()).getFixedSize(); 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 886d42d4b2f977..eef3a4e479ba8f 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -1625,10 +1625,10 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { mlir::Type dstTy = cgf.convertType(e->getType()); unsigned numElementsSrc = isa<cir::VectorType>(srcTy) - ? cast<cir::VectorType>(srcTy).getSize() + ? cast<cir::VectorType>(srcTy).getFixedSize() : 0; unsigned numElementsDst = isa<cir::VectorType>(dstTy) - ? cast<cir::VectorType>(dstTy).getSize() + ? cast<cir::VectorType>(dstTy).getFixedSize() : 0; // Use bit vector expansion for ext_vector_type boolean vectors. @@ -1653,7 +1653,7 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { if (numElementsSrc != 3 && numElementsDst == 3) { mlir::Location loc = cgf.getLoc(e->getExprLoc()); auto dstElemTy = cast<cir::VectorType>(dstTy).getElementType(); - auto dstVec4Ty = cir::VectorType::get(dstElemTy, 4); + auto dstVec4Ty = cir::VectorType::getFixed(dstElemTy, 4); src = createCastsForTypeOfSameSize(src, dstVec4Ty); src = convertVec3AndVec4(builder, loc, src, 3); return src; @@ -2989,7 +2989,7 @@ mlir::Value ScalarExprEmitter::emitVectorInitWithSubvectors(mlir::Location loc, cir::VectorType vectorType, ArrayRef<mlir::Value> inits) { - const unsigned resElts = vectorType.getSize(); + const unsigned resElts = vectorType.getFixedSize(); mlir::Value result = builder.getConstant(loc, cir::PoisonAttr::get(vectorType)); unsigned curIdx = 0; @@ -3000,7 +3000,7 @@ ScalarExprEmitter::emitVectorInitWithSubvectors(mlir::Location loc, continue; } - const unsigned initElts = initType.getSize(); + const unsigned initElts = initType.getFixedSize(); assert(curIdx + initElts <= resElts && "Sema should reject excess elements"); SmallVector<int64_t, 16> mask(resElts, -1); @@ -3055,11 +3055,12 @@ mlir::Value ScalarExprEmitter::VisitInitListExpr(InitListExpr *e) { vectorType, elements); // Zero-initialize any remaining values. - if (numInitElements < vectorType.getSize()) { + const uint64_t vectorSize = vectorType.getFixedSize(); + 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(), @@ -3274,7 +3275,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.isScalable()) { cgf.getCIRGenModule().errorNYI( e->getSourceRange(), "VisitUnaryExprOrTypeTraitExpr: sizeOf scalable vector"); @@ -3284,7 +3285,7 @@ mlir::Value ScalarExprEmitter::VisitUnaryExprOrTypeTraitExpr( } return builder.getConstant( - loc, cir::IntAttr::get(cgf.cgm.sizeTy, vecTy.getSize())); + loc, cir::IntAttr::get(cgf.cgm.sizeTy, vecTy.getFixedSize())); } // 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 6e564288447676..f07d2948cb1b23 100644 --- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp @@ -379,56 +379,43 @@ mlir::Type CIRGenTypes::convertType(QualType type) { // SVE types case BuiltinType::SveInt8: - resultType = - cir::VectorType::get(builder.getSInt8Ty(), 16, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getSInt8Ty(), 16); break; case BuiltinType::SveUint8: - resultType = - cir::VectorType::get(builder.getUInt8Ty(), 16, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getUInt8Ty(), 16); break; case BuiltinType::SveInt16: - resultType = - cir::VectorType::get(builder.getSInt16Ty(), 8, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getSInt16Ty(), 8); break; case BuiltinType::SveUint16: - resultType = - cir::VectorType::get(builder.getUInt16Ty(), 8, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getUInt16Ty(), 8); break; case BuiltinType::SveFloat16: - resultType = cir::VectorType::get(builder.getFp16Ty(), 8, - /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getFp16Ty(), 8); break; case BuiltinType::SveBFloat16: - resultType = cir::VectorType::get(builder.getBfloat16Ty(), 8, - /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getBfloat16Ty(), 8); break; case BuiltinType::SveInt32: - resultType = - cir::VectorType::get(builder.getSInt32Ty(), 4, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getSInt32Ty(), 4); break; case BuiltinType::SveUint32: - resultType = - cir::VectorType::get(builder.getUInt32Ty(), 4, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getUInt32Ty(), 4); break; case BuiltinType::SveFloat32: - resultType = cir::VectorType::get(builder.getSingleTy(), 4, - /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getSingleTy(), 4); break; case BuiltinType::SveInt64: - resultType = - cir::VectorType::get(builder.getSInt64Ty(), 2, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getSInt64Ty(), 2); break; case BuiltinType::SveUint64: - resultType = - cir::VectorType::get(builder.getUInt64Ty(), 2, /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getUInt64Ty(), 2); break; case BuiltinType::SveFloat64: - resultType = cir::VectorType::get(builder.getDoubleTy(), 2, - /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getDoubleTy(), 2); break; case BuiltinType::SveBool: - resultType = cir::VectorType::get(builder.getUIntNTy(1), 16, - /*is_scalable=*/true); + resultType = cir::VectorType::getScalable(builder.getUIntNTy(1), 16); break; // Unsigned integral types. @@ -509,7 +496,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) { #define AMDGPU_OPAQUE_PTR_TYPE(Name, Id, SingletonId, Width, Align, AS) \ case BuiltinType::Id: { \ if (BuiltinType::Id == BuiltinType::AMDGPUTexture) { \ - resultType = cir::VectorType::get(builder.getSInt32Ty(), 8); \ + resultType = cir::VectorType::getFixed(builder.getSInt32Ty(), 8); \ } else { \ resultType = builder.getPointerTo( \ cgm.voidTy, \ @@ -603,7 +590,7 @@ mlir::Type CIRGenTypes::convertType(QualType type) { case Type::Vector: { const VectorType *vec = cast<VectorType>(ty); const mlir::Type elemTy = convertType(vec->getElementType()); - resultType = cir::VectorType::get(elemTy, vec->getNumElements()); + resultType = cir::VectorType::getFixed(elemTy, vec->getNumElements()); break; } diff --git a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp index e1c57c07cceceb..023ac73178152a 100644 --- a/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRAttrs.cpp @@ -912,7 +912,10 @@ cir::ConstVectorAttr::verify(function_ref<InFlightDiagnostic()> emitError, const auto vecType = mlir::cast<cir::VectorType>(type); - if (vecType.getSize() != elts.size()) + if (vecType.isScalable()) + return emitError() << "scalable vector constants are not supported"; + + if (vecType.getFixedSize() != 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 c569a9bc899ff4..2d69135f440458 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -4242,10 +4242,13 @@ 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.isScalable()) + return emitOpError() << "scalable vectors are not supported"; + + if (getElements().size() != vecTy.getFixedSize()) { return emitOpError() << "operand count of " << getElements().size() << " doesn't match vector type " << vecTy - << " element count of " << vecTy.getSize(); + << " element count of " << vecTy.getFixedSize(); } const mlir::Type elementType = vecTy.getElementType(); @@ -4482,9 +4485,13 @@ OpFoldResult cir::VecShuffleOp::fold(FoldAdaptor adaptor) { } LogicalResult cir::VecShuffleOp::verify() { + if (getVec1().getType().isScalable() || getVec2().getType().isScalable() || + getResult().getType().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().getFixedSize()) { return emitOpError() << ": the number of elements in " << getIndices() << " and " << getResult().getType() << " don't match"; } @@ -4497,8 +4504,8 @@ 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().getFixedSize() + + getVec2().getType().getFixedSize() - 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 ecdd5fd8584d0b..fee0344028c993 100644 --- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp @@ -1501,32 +1501,34 @@ 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(), 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>(getFixedSize(), 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(); } @@ -1537,7 +1539,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()) @@ -1545,7 +1547,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); @@ -1558,7 +1560,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 {}; @@ -1580,19 +1582,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 (isScalable()) odsPrinter << "["; - odsPrinter.printStrippedAttrOrType(getSize()); - if (this->getIsScalable()) + odsPrinter.printStrippedAttrOrType(getSize().getKnownMinValue()); + if (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..fe358ba9b273d6 100644 --- a/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CIRSimplify.cpp @@ -375,9 +375,9 @@ 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.isScalable()) return mlir::failure(); - SmallVector<mlir::Attribute, 16> elements(resultType.getSize(), value); + SmallVector<mlir::Attribute, 16> elements(resultType.getFixedSize(), 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 a978d3a899c2a8..ddf60a1547f965 100644 --- a/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp +++ b/clang/lib/CIR/Dialect/Transforms/CallConvLoweringPass.cpp @@ -203,7 +203,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.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 @@ -319,8 +319,8 @@ static mlir::Type abiTypeToCIR(const llvm::abi::Type *ty, MLIRContext *ctx) { mlir::Type elemCIR = abiTypeToCIR(vecTy->getElementType(), ctx); if (!elemCIR) return nullptr; - return cir::VectorType::get(elemCIR, - vecTy->getNumElements().getFixedValue()); + return cir::VectorType::getFixed( + elemCIR, vecTy->getNumElements().getFixedValue()); }) .Case([&](const llvm::abi::RecordType *recTy) -> mlir::Type { SmallVector<mlir::Type> fieldTypes; @@ -346,8 +346,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; } @@ -407,8 +407,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 719ec9ac184ff6..6b6b932346382c 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -182,15 +182,17 @@ 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.isScalable()) + return value; auto rawIntTy = mlir::cast<mlir::IntegerType>(value.getType()); - auto paddedVecTy = - cir::VectorType::get(vecTy.getElementType(), rawIntTy.getWidth()); + auto paddedVecTy = cir::VectorType::getFixed(vecTy.getElementType(), + rawIntTy.getWidth()); mlir::Type mlirVecTy = converter.convertType(paddedVecTy); // Bitcast iP --> <P x i1>. auto v = mlir::LLVM::BitcastOp::create(rewriter, value.getLoc(), mlirVecTy, value); // Shuffle <P x i1> --> <N x i1> (N is the actual bit size). - return emitBoolVecConversion(rewriter, v, vecTy.getSize()); + return emitBoolVecConversion(rewriter, v, vecTy.getFixedSize()); } } @@ -225,9 +227,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.isScalable()) + resultTy = + mlir::VectorType::get(vecTy.getSize().getKnownMinValue(), + vecTy.getElementType(), vecTy.isScalable()); else { resultTy = mlir::IntegerType::get(origType.getContext(), vecTy.getBoolStorageWidth()); @@ -3716,13 +3719,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 { @@ -3738,10 +3739,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); @@ -4371,7 +4370,8 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter, const mlir::Type ty = converter.convertType(type.getElementType()); if (!ty) return {}; - return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()}); + return mlir::VectorType::get(type.getSize().getKnownMinValue(), ty, + {type.isScalable()}); }); converter.addConversion([&](cir::MatrixType type) -> mlir::Type { const uint64_t size = type.getNumRows() * type.getNumColumns(); @@ -5423,10 +5423,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.getFixedSize(); + 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( @@ -5518,8 +5519,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) @@ -5632,7 +5634,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().getFixedSize(); 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/clang/unittests/CIR/PointerLikeTest.cpp b/clang/unittests/CIR/PointerLikeTest.cpp index 13569b3931d69f..01707738a4c00a 100644 --- a/clang/unittests/CIR/PointerLikeTest.cpp +++ b/clang/unittests/CIR/PointerLikeTest.cpp @@ -341,7 +341,7 @@ TEST_F(CIROpenACCPointerLikeTest, testPointerToFunction) { TEST_F(CIROpenACCPointerLikeTest, testPointerToVector) { mlir::Type i32Ty = cir::IntType::get(&context, 32, true); - mlir::Type vecTy = cir::VectorType::get(i32Ty, 4); + mlir::Type vecTy = cir::VectorType::getFixed(i32Ty, 4); testNonScalarType(vecTy); } diff --git a/clang/unittests/CIR/VectorTypeABIAlignTest.cpp b/clang/unittests/CIR/VectorTypeABIAlignTest.cpp index cb36d2333494b1..798ea2153ad62d 100644 --- a/clang/unittests/CIR/VectorTypeABIAlignTest.cpp +++ b/clang/unittests/CIR/VectorTypeABIAlignTest.cpp @@ -28,7 +28,7 @@ class VectorTypeABIAlignTest : public ::testing::Test { MLIRContext context; uint64_t abiAlign(mlir::Type elementType, uint64_t size) { - cir::VectorType ty = cir::VectorType::get(elementType, size); + cir::VectorType ty = cir::VectorType::getFixed(elementType, size); OpBuilder builder(&context); auto module = ModuleOp::create(builder.getUnknownLoc()); mlir::DataLayout dl(module); 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
