[clang] [CIR][AArch64] Add lowering for `svlen` builtins (1/2) (PR #172346)
Andrzej Warzyński via cfe-commits
cfe-commits at lists.llvm.org
Tue Dec 16 08:59:39 PST 2025
https://github.com/banach-space updated https://github.com/llvm/llvm-project/pull/172346
>From d03aa53225f758305c7aeffc9d0779426f5a9df3 Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Sat, 13 Dec 2025 16:36:20 +0000
Subject: [PATCH 1/7] [CIR][AArch64] Add lowering for `svlen` builtins (1/2)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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
---
.../CIR/Dialect/Builder/CIRBaseBuilder.h | 3 +-
.../include/clang/CIR/Dialect/IR/CIRTypes.td | 14 +-
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 4 +-
.../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 46 +++++-
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 48 ++++++
clang/lib/CIR/Dialect/IR/CIRTypes.cpp | 2 +-
.../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 2 +-
.../CodeGenBuiltins/AArch64/acle_sve_len.c | 143 ++++++++++++++++++
8 files changed, 243 insertions(+), 19 deletions(-)
create mode 100644 clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
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);
+// }
>From 20ae9b1dd0e51b5e917878f58480fe2034833968 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= <andrzej.warzynski at gmail.com>
Date: Tue, 16 Dec 2025 13:50:10 +0000
Subject: [PATCH 2/7] Update
clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Co-authored-by: Andy Kaylor <akaylor at nvidia.com>
---
clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
index 8ca07ca3f17b8..696ffa42107e8 100644
--- a/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
+++ b/clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
@@ -596,7 +596,7 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
VectorType vecCast = mlir::cast<VectorType>(lhs.getType());
IntType integralTy =
getSIntNTy(getCIRIntOrFloatBitWidth(vecCast.getElementType()));
- VectorType integralVecTy = VectorType::get(integralTy, vecCast.getSize());
+ VectorType integralVecTy = cir::VectorType::get(integralTy, vecCast.getSize());
return cir::VecCmpOp::create(*this, loc, integralVecTy, kind, lhs, rhs);
}
>From efb48f0f637a8845a61b813f32c37b334813d216 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= <andrzej.warzynski at gmail.com>
Date: Tue, 16 Dec 2025 13:50:28 +0000
Subject: [PATCH 3/7] Update clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Co-authored-by: Andy Kaylor <akaylor at nvidia.com>
---
clang/include/clang/CIR/Dialect/IR/CIRTypes.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 3ca56be4e4a10..8e1f288eab822 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -447,7 +447,7 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
let parameters = (ins
CIR_VectorElementType:$elementType,
"uint64_t":$size,
- OptionalParameter<"bool">:$isScalable
+ OptionalParameter<"bool">:$is_scalable
);
let assemblyFormat = [{
>From f9bdf12337e9b26460e25df8168dda50fdbf03a4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andrzej=20Warzy=C5=84ski?= <andrzej.warzynski at gmail.com>
Date: Tue, 16 Dec 2025 13:50:36 +0000
Subject: [PATCH 4/7] Update clang/include/clang/CIR/Dialect/IR/CIRTypes.td
Co-authored-by: Andy Kaylor <akaylor at nvidia.com>
---
clang/include/clang/CIR/Dialect/IR/CIRTypes.td | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 8e1f288eab822..41f1ca8d3f295 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -445,7 +445,7 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
}];
let parameters = (ins
- CIR_VectorElementType:$elementType,
+ CIR_VectorElementType:$element_type,
"uint64_t":$size,
OptionalParameter<"bool">:$is_scalable
);
>From 51064ee89a887d8d498c2deca1a80e4a7974869c Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Tue, 16 Dec 2025 16:18:28 +0000
Subject: [PATCH 5/7] Address PR comments:
* Fix `$elementType` spelling
* Add `getFP` helpers and remove TODOs.
* Fix: `builder.createAMul` --> `builder.createNUWAMul`
---
.../include/clang/CIR/Dialect/IR/CIRTypes.td | 6 +-
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 5 +
.../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 4 +-
clang/lib/CIR/CodeGen/CIRGenTypes.cpp | 28 ++--
.../CodeGenBuiltins/AArch64/acle_sve_len.c | 121 +++++++++++-------
clang/test/CIR/IR/invalid-vector.cir | 2 +-
6 files changed, 101 insertions(+), 65 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index 41f1ca8d3f295..b553b83cf0b15 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -451,15 +451,15 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
);
let assemblyFormat = [{
- `<` $size `x` $elementType `>`
+ `<` $size `x` $element_type `>`
}];
let builders = [
TypeBuilderWithInferredContext<(ins
- "mlir::Type":$elementType, "uint64_t":$size, CArg<"bool",
+ "mlir::Type":$element_type, "uint64_t":$size, CArg<"bool",
"false">:$isScalable
), [{
- return $_get(elementType.getContext(), elementType, size, isScalable);
+ return $_get(element_type.getContext(), element_type, size, isScalable);
}]>,
];
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 2a15b1f7703be..8acad5278b732 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -285,6 +285,11 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
cir::IntType getUInt32Ty() { return typeCache.uInt32Ty; }
cir::IntType getUInt64Ty() { return typeCache.uInt64Ty; }
+ cir::FP16Type getFp16Ty() { return typeCache.fP16Ty; }
+ cir::BF16Type getBfloat6Ty() { return typeCache.bFloat16Ty; }
+ cir::SingleType getSingleTy() { return typeCache.floatTy; }
+ cir::DoubleType getDoubleTy() { return typeCache.doubleTy; }
+
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APSInt intVal);
cir::ConstantOp getConstInt(mlir::Location loc, llvm::APInt intVal);
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 7a9661b727dc7..162c466759b8a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -59,8 +59,8 @@ CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
StringRef intrinsicName = "vscale.i64";
auto vscale = emitIntrinsicCallOp(builder, loc, intrinsicName,
convertType(expr->getType()));
- return builder.createMul(loc, vscale,
- builder.getUInt64(scalingFactor, loc));
+ return builder.createNUWAMul(loc, vscale,
+ builder.getUInt64(scalingFactor, loc));
};
assert(!cir::MissingFeatures::aarch64SVEIntrinsics());
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
index 3bb075d7581f7..67c7bb18716db 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.cpp
@@ -339,10 +339,14 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
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::SveFloat16:
+ resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
+ /*isScalable=*/true);
+ break;
+ case BuiltinType::SveBFloat16:
+ resultType = cir::VectorType::get(builder.getFp16Ty(), 8,
+ /*isScalable=*/true);
+ break;
case BuiltinType::SveInt32:
resultType =
cir::VectorType::get(builder.getSInt32Ty(), 4, /*isScalable=*/true);
@@ -351,10 +355,10 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
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::SveFloat32:
+ resultType = cir::VectorType::get(builder.getSingleTy(), 4,
+ /*isScalable=*/true);
+ break;
case BuiltinType::SveInt64:
resultType =
cir::VectorType::get(builder.getSInt64Ty(), 2, /*isScalable=*/true);
@@ -363,10 +367,10 @@ mlir::Type CIRGenTypes::convertType(QualType type) {
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;
+ case BuiltinType::SveFloat64:
+ resultType = cir::VectorType::get(builder.getDoubleTy(), 2,
+ /*isScalable=*/true);
+ break;
// Unsigned integral types.
case BuiltinType::Char8:
diff --git a/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c b/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
index 3ad2ddef04030..0bacdbb151cd8 100644
--- a/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
+++ b/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
@@ -3,9 +3,12 @@
// 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
+
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -fclangir -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM_OGCG_CIR
+// 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_OGCG_CIR
+
+// RUN: %clang_cc1 -triple aarch64 -target-feature +sve -disable-O0-optnone -Werror -Wall -emit-llvm -o - %s | FileCheck %s --check-prefixes=ALL,LLVM_OGCG_CIR
+// 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,LLVM_OGCG_CIR
#include <arm_sve.h>
@@ -27,10 +30,10 @@ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C16]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 16
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 16
return SVE_ACLE_FUNC(svlen,_u8,,)(op);
}
@@ -39,10 +42,10 @@ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C16]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 16
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 16
return SVE_ACLE_FUNC(svlen,_s8,,)(op);
}
@@ -51,10 +54,10 @@ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 8
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 8
return SVE_ACLE_FUNC(svlen,_u16,,)(op);
}
@@ -63,34 +66,46 @@ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 8
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw 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);
-// }
+// ALL-LABEL: @test_svlen_f16(
+uint64_t test_svlen_f16(svfloat16_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]]) nuw : !u64i
+
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 8
+ return SVE_ACLE_FUNC(svlen,_f16,,)(op);
+}
+
+// ALL-LABEL: @test_svlen_bf16(
+uint64_t test_svlen_bf16(svbfloat16_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]]) nuw : !u64i
-// TODO: Waiting for FP type helpers
-// uint64_t test_svlen_bf16(svbfloat16_t op) MODE_ATTR
-// {
-// return SVE_ACLE_FUNC(svlen,_bf16,,)(op);
-// }
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 8
+ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 4
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 4
return SVE_ACLE_FUNC(svlen,_u32,,)(op);
}
@@ -99,28 +114,34 @@ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 4
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw 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_f32(
+uint64_t test_svlen_f32(svfloat32_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]]) nuw : !u64i
+
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 4
+ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 2
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 2
return SVE_ACLE_FUNC(svlen,_u64,,)(op);
}
@@ -129,15 +150,21 @@ 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
+// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) nuw : !u64i
-// LLVM: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
-// LLVM: [[RES:%.*]] = mul i64 [[VSCALE]], 2
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw 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);
-// }
+// ALL-LABEL: @test_svlen_f64
+uint64_t test_svlen_f64(svfloat64_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]]) nuw : !u64i
+
+// LLVM_OGCG_CIR: [[VSCALE:%.*]] = call i64 @llvm.vscale.i64()
+// LLVM_OGCG_CIR: [[RES:%.*]] = mul nuw i64 [[VSCALE]], 2
+ return SVE_ACLE_FUNC(svlen,_f64,,)(op);
+}
diff --git a/clang/test/CIR/IR/invalid-vector.cir b/clang/test/CIR/IR/invalid-vector.cir
index 679994925786e..7b8c89cc58248 100644
--- a/clang/test/CIR/IR/invalid-vector.cir
+++ b/clang/test/CIR/IR/invalid-vector.cir
@@ -4,7 +4,7 @@
module {
-// expected-error @below {{failed to verify 'elementType'}}
+// expected-error @below {{failed to verify 'element_type'}}
cir.global external @vec_b = #cir.zero : !cir.vector<4 x !cir.array<!s32i x 10>>
}
>From 220de86345523b63ea06525cba85bfa78774b1d2 Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Tue, 16 Dec 2025 16:53:24 +0000
Subject: [PATCH 6/7] Address PR comments
* Replace `vscaleTimesFactor` lambda with a static function:
`genVscaleTimesFactor`
* Replace `"vscale.i64"` with `"vscale"`.
---
.../include/clang/CIR/Dialect/IR/CIRTypes.td | 9 +++---
.../lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp | 30 ++++++++++---------
.../CodeGenBuiltins/AArch64/acle_sve_len.c | 24 +++++++--------
3 files changed, 32 insertions(+), 31 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index b553b83cf0b15..d9be7afcb7559 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -454,11 +454,10 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
`<` $size `x` $element_type `>`
}];
- let builders = [
- TypeBuilderWithInferredContext<(ins
- "mlir::Type":$element_type, "uint64_t":$size, CArg<"bool",
- "false">:$isScalable
- ), [{
+ let builders = [TypeBuilderWithInferredContext<
+ (ins "mlir::Type":$element_type, "uint64_t":$size,
+ CArg<"bool", "false">:$isScalable),
+ [{
return $_get(element_type.getContext(), element_type, size, isScalable);
}]>,
];
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
index 162c466759b8a..36852c03546e9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenBuiltinAArch64.cpp
@@ -42,6 +42,16 @@ static mlir::Value emitIntrinsicCallOp(CIRGenBuilderTy &builder,
.getResult();
}
+// Generate vscale * scalingFactor
+static mlir::Value genVscaleTimesFactor(mlir::Location loc,
+ CIRGenBuilderTy builder,
+ mlir::Type cirTy,
+ int32_t scalingFactor) {
+ auto vscale = emitIntrinsicCallOp(builder, loc, "vscale", cirTy);
+ return builder.createNUWAMul(loc, vscale,
+ builder.getUInt64(scalingFactor, loc));
+}
+
std::optional<mlir::Value>
CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
const CallExpr *expr) {
@@ -53,22 +63,14 @@ 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.createNUWAMul(loc, vscale,
- builder.getUInt64(scalingFactor, loc));
- };
-
assert(!cir::MissingFeatures::aarch64SVEIntrinsics());
switch (builtinID) {
default:
return std::nullopt;
+ mlir::Location loc = getLoc(expr->getExprLoc());
+
case SVE::BI__builtin_sve_svreinterpret_b:
case SVE::BI__builtin_sve_svreinterpret_c:
case SVE::BI__builtin_sve_svpsel_lane_b8:
@@ -129,20 +131,20 @@ CIRGenFunction::emitAArch64SVEBuiltinExpr(unsigned builtinID,
return mlir::Value{};
case SVE::BI__builtin_sve_svlen_u8:
case SVE::BI__builtin_sve_svlen_s8:
- return vscaleTimesFactor(16);
+ return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 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);
+ return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 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);
+ return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 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);
+ return genVscaleTimesFactor(loc, builder, convertType(expr->getType()), 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/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c b/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
index 0bacdbb151cd8..ac202ef792ff9 100644
--- a/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
+++ b/clang/test/CIR/CodeGenBuiltins/AArch64/acle_sve_len.c
@@ -28,7 +28,7 @@
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C16:.*]] = cir.const #cir.int<16> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C16]]) nuw : !u64i
@@ -40,7 +40,7 @@ uint64_t test_svlen_u8(svuint8_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C16:.*]] = cir.const #cir.int<16> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C16]]) nuw : !u64i
@@ -52,7 +52,7 @@ uint64_t test_svlen_s8(svint8_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C8:.*]] = cir.const #cir.int<8> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) nuw : !u64i
@@ -64,7 +64,7 @@ uint64_t test_svlen_u16(svuint16_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C8:.*]] = cir.const #cir.int<8> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) nuw : !u64i
@@ -76,7 +76,7 @@ uint64_t test_svlen_s16(svint16_t op) MODE_ATTR
// ALL-LABEL: @test_svlen_f16(
uint64_t test_svlen_f16(svfloat16_t op) MODE_ATTR
{
-// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C8:.*]] = cir.const #cir.int<8> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) nuw : !u64i
@@ -88,7 +88,7 @@ uint64_t test_svlen_f16(svfloat16_t op) MODE_ATTR
// ALL-LABEL: @test_svlen_bf16(
uint64_t test_svlen_bf16(svbfloat16_t op) MODE_ATTR
{
-// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C8:.*]] = cir.const #cir.int<8> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C8]]) nuw : !u64i
@@ -100,7 +100,7 @@ uint64_t test_svlen_bf16(svbfloat16_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C4:.*]] = cir.const #cir.int<4> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) nuw : !u64i
@@ -112,7 +112,7 @@ uint64_t test_svlen_u32(svuint32_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C4:.*]] = cir.const #cir.int<4> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) nuw : !u64i
@@ -124,7 +124,7 @@ uint64_t test_svlen_s32(svint32_t op) MODE_ATTR
// ALL-LABEL: @test_svlen_f32(
uint64_t test_svlen_f32(svfloat32_t op) MODE_ATTR
{
-// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C4:.*]] = cir.const #cir.int<4> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C4]]) nuw : !u64i
@@ -136,7 +136,7 @@ uint64_t test_svlen_f32(svfloat32_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C2:.*]] = cir.const #cir.int<2> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) nuw : !u64i
@@ -148,7 +148,7 @@ uint64_t test_svlen_u64(svuint64_t op) MODE_ATTR
// 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: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C2:.*]] = cir.const #cir.int<2> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) nuw : !u64i
@@ -160,7 +160,7 @@ uint64_t test_svlen_s64(svint64_t op) MODE_ATTR
// ALL-LABEL: @test_svlen_f64
uint64_t test_svlen_f64(svfloat64_t op) MODE_ATTR
{
-// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale.i64" : () -> !u64i
+// CIR: %[[VSCALE:.*]] = cir.call_llvm_intrinsic "vscale" : () -> !u64i
// CIR: %[[C2:.*]] = cir.const #cir.int<2> : !u64i
// CIR: %[[BINOP:.*]] = cir.binop(mul, %[[VSCALE]], %[[C2]]) nuw : !u64i
>From e1c40d24f6b6d90bb82310e706c587df0d4e339b Mon Sep 17 00:00:00 2001
From: Andrzej Warzynski <andrzej.warzynski at arm.com>
Date: Tue, 16 Dec 2025 16:59:09 +0000
Subject: [PATCH 7/7] Revert TD change
---
clang/include/clang/CIR/Dialect/IR/CIRTypes.td | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
index d9be7afcb7559..b553b83cf0b15 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIRTypes.td
@@ -454,10 +454,11 @@ def CIR_VectorType : CIR_Type<"Vector", "vector", [
`<` $size `x` $element_type `>`
}];
- let builders = [TypeBuilderWithInferredContext<
- (ins "mlir::Type":$element_type, "uint64_t":$size,
- CArg<"bool", "false">:$isScalable),
- [{
+ let builders = [
+ TypeBuilderWithInferredContext<(ins
+ "mlir::Type":$element_type, "uint64_t":$size, CArg<"bool",
+ "false">:$isScalable
+ ), [{
return $_get(element_type.getContext(), element_type, size, isScalable);
}]>,
];
More information about the cfe-commits
mailing list