-
Notifications
You must be signed in to change notification settings - Fork 15.5k
[CIR][AArch64] Add lowering for svlen builtins (1/2)
#172346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
[CIR][AArch64] Add lowering for svlen builtins (1/2)
#172346
Conversation
This patch adds lowering support for integer `svlen` builtins. Floating-point variants are omitted for now and will be added once FP type helpers (e.g., `getFP32Ty()`) become available. Because svlen builtins take scalable vector types (e.g., `svuint64_t`), this change also extends `cir::VectorType` to represent scalable vectors. Since `cir::VectorType` is ultimately converted to MLIR’s builtin `VectorType` during lowering to LLVM IR, the implementation follows the same approach: scalability is modelled using an additional boolean member (`isScalable`, defaulting to `false`). Further work will be needed to properly support scalable vectors within CIR: * `cir::VectorType::getTypeSizeInBits` currently returns the compile-time base vector size. Its meaning and usefulness for scalable vectors are unclear and may need re-design. * The assembly format for `cir::VectorType` will require a custom parser and printer to encode scalability (and agreement on the concrete syntax). This is not required for this patch. References: * https://arm-software.github.io/acle/main/acle.html#markdown-toc-sve-vector-types * https://developer.arm.com/documentation/100891/0609/coding-considerations/using-sve-intrinsics-directly-in-your-c-code
|
@llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Andrzej Warzyński (banach-space) ChangesThis patch adds lowering support for integer Because svlen builtins take scalable vector types (e.g., Further work will be needed to properly support scalable vectors within
References:
Full diff: https://github.com/llvm/llvm-project/pull/172346.diff 8 Files Affected:
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index b4b02e24f85cc..8ca07ca3f17b8 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -596,8 +596,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
IntType integralTy =
getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType()));
- VectorType integralVecTy =
- VectorType::get(context, integralTy, vecCast.getSize());
+ VectorType integralVecTy = VectorType::get(integralTy, vecCast.getSize());
return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs);
}
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 59b97f0c6d39a..3ca56be4e4a10 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -422,8 +422,9 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
]> {
let summary = "CIR vector type";
let description = [{
- The `!cir.vector` type represents a fixed-size, one-dimensional vector.
- It takes two parameters: the element type and the number of elements.
+ 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`).
Syntax:
@@ -445,7 +446,8 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
let parameters = (ins
CIR_VectorElementType:$elementType,
- "uint64_t":$size
+ "uint64_t":$size,
+ OptionalParameter<"bool">:$isScalable
);
let assemblyFormat = [{
@@ -454,9 +456,10 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
let builders = [
TypeBuilderWithInferredContext<(ins
- "mlir::Type":$elementType, "uint64_t":$size
+ "mlir::Type":$elementType, "uint64_t":$size, CArg<"bool",
+ "false">:$isScalable
), [{
- return $_get(elementType.getContext(), elementType, size);
+ return $_get(elementType.getContext(), elementType, size, isScalable);
}]>,
];
@@ -467,6 +470,7 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
}];
let genVerifyDecl = 1;
+ let skipDefaultBuilders = 1;
}
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 5b10bddd054ea..2a15b1f7703be 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -628,8 +628,8 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
createVecShuffle(mlir::Location loc, mlir::Value vec1, mlir::Value vec2,
llvm::ArrayRef<mlir::Attribute> maskAttrs) {
auto vecType = mlir::cast<cir::VectorType>(vec1.getType());
- auto resultTy = cir::VectorType::get(getContext(), vecType.getElementType(),
- maskAttrs.size());
+ auto resultTy =
+ cir::VectorType::get(vecType.getElementType(), maskAttrs.size());
return cir::VecShuffleOp::create(*this, loc, resultTy, vec1, vec2,
getArrayAttr(maskAttrs));
}
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 696180458a2f6..7a9661b727dc7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -11,6 +11,7 @@
//
//===----------------------------------------------------------------------===//
+#include "CIRGenBuilder.h"
#include "CIRGenFunction.h"
#include "clang/CIR/MissingFeatures.h"
@@ -30,6 +31,17 @@ using namespace clang;
using namespace clang::CIRGen;
using namespace llvm;
+template <typename... Operands>
+static mlir::Value emitIntrinsicCallOp(CIRGenBuilderTy &builder,
+ mlir::Location loc, const StringRef str,
+ const mlir::Type &resTy,
+ Operands &&...op) {
+ return cir::LLVMIntrinsicCallOp::create(builder, loc,
+ builder.getStringAttr(str), resTy,
+ std::forward<Operands>(op)...)
+ .getResult();
+}
+
std::optional<mlir::Value>
CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
const CallExpr *expr) {
@@ -41,6 +53,16 @@ CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
return mlir::Value{};
}
+ mlir::Location loc = getLoc(expr->getExprLoc());
+ // Generate vscale * scalingFactor
+ auto vscaleTimesFactor = [&](int32_t scalingFactor) {
+ StringRef intrinsicName = "vscale.i64";
+ auto vscale = emitIntrinsicCallOp(builder, loc, intrinsicName,
+ convertType(expr->getType()));
+ return builder.createMul(loc, vscale,
+ builder.getUInt64(scalingFactor, loc));
+ };
+
assert(!cir::MissingFeatures::aarch64SVEIntrinsics());
switch (builtinID) {
@@ -101,18 +123,26 @@ CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
case SVE::BI__builtin_sve_svdupq_n_s32:
case SVE::BI__builtin_sve_svpfalse_b:
case SVE::BI__builtin_sve_svpfalse_c:
- case SVE::BI__builtin_sve_svlen_bf16:
- case SVE::BI__builtin_sve_svlen_f16:
- case SVE::BI__builtin_sve_svlen_f32:
- case SVE::BI__builtin_sve_svlen_f64:
- case SVE::BI__builtin_sve_svlen_s8:
- case SVE::BI__builtin_sve_svlen_s16:
- case SVE::BI__builtin_sve_svlen_s32:
- case SVE::BI__builtin_sve_svlen_s64:
+ cgm.errorNYI(expr->getSourceRange(),
+ std::string("unimplemented AArch64 builtin call: ") +
+ getContext().BuiltinInfo.getName(builtinID));
+ return mlir::Value{};
case SVE::BI__builtin_sve_svlen_u8:
+ case SVE::BI__builtin_sve_svlen_s8:
+ return vscaleTimesFactor(16);
case SVE::BI__builtin_sve_svlen_u16:
+ case SVE::BI__builtin_sve_svlen_s16:
+ case SVE::BI__builtin_sve_svlen_f16:
+ case SVE::BI__builtin_sve_svlen_bf16:
+ return vscaleTimesFactor(8);
case SVE::BI__builtin_sve_svlen_u32:
+ case SVE::BI__builtin_sve_svlen_s32:
+ case SVE::BI__builtin_sve_svlen_f32:
+ return vscaleTimesFactor(4);
case SVE::BI__builtin_sve_svlen_u64:
+ case SVE::BI__builtin_sve_svlen_s64:
+ case SVE::BI__builtin_sve_svlen_f64:
+ return vscaleTimesFactor(2);
case SVE::BI__builtin_sve_svtbl2_u8:
case SVE::BI__builtin_sve_svtbl2_s8:
case SVE::BI__builtin_sve_svtbl2_u16:
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 7f000ece8a494..3bb075d7581f7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -7,6 +7,7 @@
#include "clang/AST/GlobalDecl.h"
#include "clang/AST/Type.h"
#include "clang/Basic/TargetInfo.h"
+#include "clang/CIR/Dialect/IR/CIRTypes.h"
#include <cassert>
@@ -320,6 +321,53 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
cir::IntType::get(&getMLIRContext(), astContext.getTypeSize(ty),
/*isSigned=*/true);
break;
+
+ // SVE types
+ case BuiltinType::SveInt8:
+ resultType =
+ cir::VectorType::get(builder.getSInt8Ty(), 16, /*isScalable=*/true);
+ break;
+ case BuiltinType::SveUint8:
+ resultType =
+ cir::VectorType::get(builder.getUInt8Ty(), 16, /*isScalable=*/true);
+ break;
+ case BuiltinType::SveInt16:
+ resultType =
+ cir::VectorType::get(builder.getSInt16Ty(), 8, /*isScalable=*/true);
+ break;
+ case BuiltinType::SveUint16:
+ resultType =
+ cir::VectorType::get(builder.getUInt16Ty(), 8, /*isScalable=*/true);
+ break;
+ // TODO: Waiting for FP type helpers
+ // case BuiltinType::SveFloat16:
+ // resultType = cir::VectorType::get(builder.getF16Type(), 8,
+ // /*isScalable=*/true); break;
+ case BuiltinType::SveInt32:
+ resultType =
+ cir::VectorType::get(builder.getSInt32Ty(), 4, /*isScalable=*/true);
+ break;
+ case BuiltinType::SveUint32:
+ resultType =
+ cir::VectorType::get(builder.getUInt32Ty(), 4, /*isScalable=*/true);
+ break;
+ // TODO: Waiting for FP type helpers
+ // case BuiltinType::SveFloat32:
+ // resultType = cir::VectorType::get(builder.getF32Type(), 4,
+ // /*isScalable=*/true); break;
+ case BuiltinType::SveInt64:
+ resultType =
+ cir::VectorType::get(builder.getSInt64Ty(), 2, /*isScalable=*/true);
+ break;
+ case BuiltinType::SveUint64:
+ resultType =
+ cir::VectorType::get(builder.getUInt64Ty(), 2, /*isScalable=*/true);
+ break;
+ // TODO: Waiting for FP type helpers
+ // case BuiltinType::SveFloat64:
+ // resultType = cir::VectorType::get(builder.getF64Type(), 2,
+ // /*isScalable=*/true); break;
+
// Unsigned integral types.
case BuiltinType::Char8:
case BuiltinType::Char16:
diff --git a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
index 9a37a4f4e3996..c7531022fdfb8 100644
--- a/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRTypes.cpp
@@ -822,7 +822,7 @@ cir::VectorType::getABIAlignment(const ::mlir::DataLayout &dataLayout,
mlir::LogicalResult cir::VectorType::verify(
llvm::function_ref<mlir::InFlightDiagnostic()> emitError,
- mlir::Type elementType, uint64_t size) {
+ mlir::Type elementType, uint64_t size, bool scalable) {
if (size == 0)
return emitError() << "the number of vector elements must be non-zero";
return success();
diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
index 7d854997848aa..7c9cf8e2c2e2d 100644
--- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
+++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
@@ -2910,7 +2910,7 @@ static void prepareTypeConverter(mlir::LLVMTypeConverter &converter,
});
converter.addConversion([&](cir::VectorType type) -> mlir::Type {
const mlir::Type ty = converter.convertType(type.getElementType());
- return mlir::VectorType::get(type.getSize(), ty);
+ return mlir::VectorType::get(type.getSize(), ty, {type.getIsScalable()});
});
converter.addConversion([&](cir::BoolType type) -> mlir::Type {
return mlir::IntegerType::get(type.getContext(), 1,
diff --git a/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c b/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
new file mode 100644
index 0000000000000..3ad2ddef04030
--- /dev/null
+++ b/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
@@ -0,0 +1,143 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 6
+// REQUIRES: aarch64-registered-target
+
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-cir -o - %s | FileCheck %s --check-prefixes=ALL,CIR
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-cir -o - %s | FileCheck %s --check-prefixes=ALL,CIR
+//
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM
+// RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM
+
+#include <arm_sve.h>
+
+#if defined __ARM_FEATURE_SME
+#define MODE_ATTR __arm_streaming
+#else
+#define MODE_ATTR
+#endif
+
+#ifdef SVE_OVERLOADED_FORMS
+// A simple used,unused... macro, long enough to represent any SVE builtin.
+#define SVE_ACLE_FUNC(A1,A2_UNUSED,A3,A4_UNUSED) A1##A3
+#else
+#define SVE_ACLE_FUNC(A1,A2,A3,A4) A1##A2##A3##A4
+#endif
+
+// ALL-LABEL: @test_svlen_u8
+uint64_t test_svlen_u8(svuint8_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C16:.*]] = cir.const #cir.int<16> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C16]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 16
+ return SVE_ACLE_FUNC(svlen,_u8,,)(op);
+}
+
+// ALL-LABEL: @test_svlen_s8(
+uint64_t test_svlen_s8(svint8_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C16:.*]] = cir.const #cir.int<16> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C16]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 16
+ return SVE_ACLE_FUNC(svlen,_s8,,)(op);
+}
+
+// ALL-LABEL: @test_svlen_u16(
+uint64_t test_svlen_u16(svuint16_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C8:.*]] = cir.const #cir.int<8> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 8
+ return SVE_ACLE_FUNC(svlen,_u16,,)(op);
+}
+
+// ALL-LABEL: @test_svlen_s16(
+uint64_t test_svlen_s16(svint16_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C8:.*]] = cir.const #cir.int<8> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 8
+ return SVE_ACLE_FUNC(svlen,_s16,,)(op);
+}
+
+// TODO: Waiting for FP type helpers
+// uint64_t test_svlen_f16(svfloat16_t op) MODE_ATTR
+// {
+// return SVE_ACLE_FUNC(svlen,_f16,,)(op);
+// }
+
+// TODO: Waiting for FP type helpers
+// uint64_t test_svlen_bf16(svbfloat16_t op) MODE_ATTR
+// {
+// return SVE_ACLE_FUNC(svlen,_bf16,,)(op);
+// }
+
+// ALL-LABEL: @test_svlen_u32(
+uint64_t test_svlen_u32(svuint32_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 4
+ return SVE_ACLE_FUNC(svlen,_u32,,)(op);
+}
+
+// ALL-LABEL: @test_svlen_s32(
+uint64_t test_svlen_s32(svint32_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C4:.*]] = cir.const #cir.int<4> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 4
+ return SVE_ACLE_FUNC(svlen,_s32,,)(op);
+}
+
+// TODO: Waiting for FP type helpers
+// uint64_t test_svlen_f32(svfloat32_t op) MODE_ATTR
+// {
+// return SVE_ACLE_FUNC(svlen,_f32,,)(op);
+// }
+
+// ALL-LABEL: @test_svlen_u64(
+uint64_t test_svlen_u64(svuint64_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C2:.*]] = cir.const #cir.int<2> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 2
+ return SVE_ACLE_FUNC(svlen,_u64,,)(op);
+}
+
+// ALL-LABEL: @test_svlen_s64
+uint64_t test_svlen_s64(svint64_t op) MODE_ATTR
+{
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[C2:.*]] = cir.const #cir.int<2> : !u64i
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) : !u64i
+
+// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 2
+ return SVE_ACLE_FUNC(svlen,_s64,,)(op);
+}
+
+// TODO: Waiting for FP type helpers
+// uint64_t test_svlen_f64(svfloat64_t op) MODE_ATTR
+// {
+// return SVE_ACLE_FUNC(svlen,_f64,,)(op);
+// }
|
andykaylor
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for getting us started on AArch64 builtins!
| getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType())); | ||
| VectorType integralVecTy = | ||
| VectorType::get(context, integralTy, vecCast.getSize()); | ||
| VectorType integralVecTy = VectorType::get(integralTy, vecCast.getSize()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| VectorType integralVecTy = VectorType::get(integralTy, vecCast.getSize()); | |
| VectorType integralVecTy = cir::VectorType::get(integralTy, vecCast.getSize()); |
We've been trying to make cir namespace uses explicit to avoid ambiguity, but it looks like we missed this one (and the cast earlier in this function).
| CIR_VectorElementType:$elementType, | ||
| "uint64_t":$size | ||
| "uint64_t":$size, | ||
| OptionalParameter<"bool">:$isScalable |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| OptionalParameter<"bool">:$isScalable | |
| OptionalParameter<"bool">:$is_scalable |
We've decided to standardize on snake_case in our dialect definition files, but a lot of places haven't been updated since we made that decision.
| }]; | ||
|
|
||
| let parameters = (ins | ||
| CIR_VectorElementType:$elementType, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| CIR_VectorElementType:$elementType, | |
| CIR_VectorElementType:$element_type, |
| StringRef intrinsicName = "vscale.i64"; | ||
| auto vscale = emitIntrinsicCallOp(builder, loc, intrinsicName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| StringRef intrinsicName = "vscale.i64"; | |
| auto vscale = emitIntrinsicCallOp(builder, loc, intrinsicName, | |
| StringRef intrinsicName = "vscale.i64"; | |
| auto vscale = emitIntrinsicCallOp(builder, loc, "vscale", |
The suffix will get added automatically during lowering to LLVM IR.
Do you think it's useful to add a cir.vscale operation to make this easier to identify in transformation passes?
| StringRef intrinsicName = "vscale.i64"; | ||
| auto vscale = emitIntrinsicCallOp(builder, loc, intrinsicName, | ||
| convertType(expr->getType())); | ||
| return builder.createMul(loc, vscale, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| return builder.createMul(loc, vscale, | |
| return builder.createNUWAMul(loc, vscale, |
I'm not sure why this isn't createNUWMul
|
|
||
| mlir::Location loc = getLoc(expr->getExprLoc()); | ||
| // Generate vscale * scalingFactor | ||
| auto vscaleTimesFactor = [&](int32_t scalingFactor) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe make this a separate static function rather than a lambda?
| break; | ||
| // TODO: Waiting for FP type helpers | ||
| // case BuiltinType::SveFloat16: | ||
| // resultType = cir::VectorType::get(builder.getF16Type(), 8, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the type helpers? We already have fP16Ty, floatTy, and doubleTy in CIRGenTypeCache so it should be trivial.
| // RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM | ||
| // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| // RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM | |
| // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM | |
| // RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM | |
| // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM | |
| // RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,OGCG | |
| // RUN: %clang_cc1 -DSVE_OVERLOADED_FORMS -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,OGCG | |
Can you add checks for OGCG so we can visually compare the LLVM output via CIR to the direct LLVM output to verify that we're doing the same thing?
This patch adds lowering support for integer
svlenbuiltins.Floating-point variants are omitted for now and will be added once FP
type helpers (e.g.,
getFP32Ty()) become available.Because svlen builtins take scalable vector types (e.g.,
svuint64_t),this change also extends
cir::VectorTypeto represent scalablevectors. Since
cir::VectorTypeis ultimately converted to MLIR’sbuiltin
VectorTypeduring lowering to LLVM IR, the implementationfollows the same approach: scalability is modelled using an additional
boolean member (
isScalable, defaulting tofalse).Further work will be needed to properly support scalable vectors within
CIR:
cir::VectorType::getTypeSizeInBitscurrently returns thecompile-time base vector size. Its meaning and usefulness for scalable
vectors are unclear and may need re-design.
cir::VectorTypewill require a custom parserand printer to encode scalability (and agreement on the concrete
syntax). This is not required for this patch.
References: