[clang] [llvm] [LLVM][SVE] Add dedicated intrinsics to cast between svcount_t and svbool_t. (PR #218667)
Paul Walker via llvm-commits
llvm-commits at lists.llvm.org
Tue Aug 25 05:11:52 PDT 2026
https://github.com/paulwalker-arm created https://github.com/llvm/llvm-project/pull/218667
This makes the casting behaviour more explicit:
> to/from_svbool : lane-count changing casts
> to/from_svcount : reinterpretation casts
This is the final piece after https://github.com/llvm/llvm-project/issues/217256 and https://github.com/llvm/llvm-project/issues/217360.
>From 2716c6735b589cc21f11c5444890fa43760d458e Mon Sep 17 00:00:00 2001
From: Paul Walker <paul.walker at arm.com>
Date: Tue, 18 Aug 2026 17:27:45 +0000
Subject: [PATCH] [LLVM][SVE] Add dedicated intrinsics to cast between
svcount_t and svbool_t.
This makes the casting behaviour more explicit:
to/from_svbool : lane-count changing casts
to/from_svcount : reinterpretation casts
---
clang/lib/CodeGen/TargetBuiltins/ARM.cpp | 8 ++-----
.../acle_sme2_reinterpret_svcount_svbool.c | 8 +++----
llvm/include/llvm/IR/IntrinsicsAArch64.td | 16 ++++++++-----
llvm/lib/IR/AutoUpgrade.cpp | 22 ++++++++++++++++++
.../Target/AArch64/AArch64ISelLowering.cpp | 7 +++---
.../Bitcode/upgrade-aarch64-sve-intrinsics.ll | 18 +++++++++++++++
.../AArch64/sve-intrinsics-reinterpret.ll | 23 ++-----------------
7 files changed, 61 insertions(+), 41 deletions(-)
diff --git a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
index 5cddeef5e0f37..f247226aafa07 100644
--- a/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
+++ b/clang/lib/CodeGen/TargetBuiltins/ARM.cpp
@@ -4064,17 +4064,13 @@ Value *CodeGenFunction::EmitAArch64SVEBuiltinExpr(unsigned BuiltinID,
return nullptr;
case SVE::BI__builtin_sve_svreinterpret_b: {
- auto SVCountTy =
- llvm::TargetExtType::get(getLLVMContext(), "aarch64.svcount");
Function *CastFromSVCountF =
- CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_to_svbool, SVCountTy);
+ CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_from_svcount);
return Builder.CreateCall(CastFromSVCountF, Ops[0]);
}
case SVE::BI__builtin_sve_svreinterpret_c: {
- auto SVCountTy =
- llvm::TargetExtType::get(getLLVMContext(), "aarch64.svcount");
Function *CastToSVCountF =
- CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_from_svbool, SVCountTy);
+ CGM.getIntrinsic(Intrinsic::aarch64_sve_convert_to_svcount);
return Builder.CreateCall(CastToSVCountF, Ops[0]);
}
diff --git a/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c
index 4c059e350a182..abffa8c7be3b3 100644
--- a/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c
+++ b/clang/test/CodeGen/AArch64/sme2-intrinsics/acle_sme2_reinterpret_svcount_svbool.c
@@ -26,12 +26,12 @@
// CHECK-LABEL: @test_svreinterpret_svbool_svcnt(
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") [[CNT:%.*]])
+// CHECK-NEXT: [[TMP0:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.from.svcount(target("aarch64.svcount") [[CNT:%.*]])
// CHECK-NEXT: ret <vscale x 16 x i1> [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z31test_svreinterpret_svbool_svcntu11__SVCount_t(
// CPP-CHECK-NEXT: entry:
-// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") [[CNT:%.*]])
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.from.svcount(target("aarch64.svcount") [[CNT:%.*]])
// CPP-CHECK-NEXT: ret <vscale x 16 x i1> [[TMP0]]
//
svbool_t test_svreinterpret_svbool_svcnt(svcount_t cnt) MODE_ATTR
@@ -41,12 +41,12 @@ svbool_t test_svreinterpret_svbool_svcnt(svcount_t cnt) MODE_ATTR
// CHECK-LABEL: @test_svreinterpret_svcnt_svbool(
// CHECK-NEXT: entry:
-// CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1> [[PG:%.*]])
+// CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.to.svcount(<vscale x 16 x i1> [[PG:%.*]])
// CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]]
//
// CPP-CHECK-LABEL: @_Z31test_svreinterpret_svcnt_svboolu10__SVBool_t(
// CPP-CHECK-NEXT: entry:
-// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1> [[PG:%.*]])
+// CPP-CHECK-NEXT: [[TMP0:%.*]] = tail call target("aarch64.svcount") @llvm.aarch64.sve.convert.to.svcount(<vscale x 16 x i1> [[PG:%.*]])
// CPP-CHECK-NEXT: ret target("aarch64.svcount") [[TMP0]]
//
svcount_t test_svreinterpret_svcnt_svbool(svbool_t pg) MODE_ATTR
diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td
index 8fbe68f98cc63..8356bbb8640a1 100644
--- a/llvm/include/llvm/IR/IntrinsicsAArch64.td
+++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td
@@ -2339,13 +2339,17 @@ def int_aarch64_sve_ptest_last : AdvSIMD_SVE_PTEST_Intrinsic<[IntrSpeculatable]
// Reinterpreting data
//
-def int_aarch64_sve_convert_from_svbool : DefaultAttrsIntrinsic<[llvm_any_ty],
- [llvm_nxv16i1_ty],
- [IntrNoMem, IntrSpeculatable]>;
+def int_aarch64_sve_convert_from_svbool : DefaultAttrsIntrinsic<
+ [llvm_anyvector_ty], [llvm_nxv16i1_ty], [IntrNoMem, IntrSpeculatable]>;
-def int_aarch64_sve_convert_to_svbool : DefaultAttrsIntrinsic<[llvm_nxv16i1_ty],
- [llvm_any_ty],
- [IntrNoMem, IntrSpeculatable]>;
+def int_aarch64_sve_convert_to_svbool : DefaultAttrsIntrinsic<
+ [llvm_nxv16i1_ty], [llvm_anyvector_ty], [IntrNoMem, IntrSpeculatable]>;
+
+def int_aarch64_sve_convert_from_svcount : DefaultAttrsIntrinsic<
+ [llvm_nxv16i1_ty], [llvm_aarch64_svcount_ty], [IntrNoMem, IntrSpeculatable]>;
+
+def int_aarch64_sve_convert_to_svcount : DefaultAttrsIntrinsic<
+ [llvm_aarch64_svcount_ty], [llvm_nxv16i1_ty], [IntrNoMem, IntrSpeculatable]>;
//
// Gather loads: scalar base + vector offsets
diff --git a/llvm/lib/IR/AutoUpgrade.cpp b/llvm/lib/IR/AutoUpgrade.cpp
index 9865816e36959..59366f69b2709 100644
--- a/llvm/lib/IR/AutoUpgrade.cpp
+++ b/llvm/lib/IR/AutoUpgrade.cpp
@@ -1047,6 +1047,28 @@ static bool upgradeArmOrAarch64IntrinsicFunction(bool IsArm, Function *F,
return true;
}
+ if (Name.consume_front("convert.from.svbool")) {
+ // 'aarch64.sve.convert.from.svbool'
+ auto *TTy = dyn_cast<TargetExtType>(F->getReturnType());
+ if (!TTy || TTy->getName() != "aarch64.svcount")
+ return false;
+
+ Intrinsic::ID ID = Intrinsic::aarch64_sve_convert_to_svcount;
+ NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
+ return true;
+ }
+
+ if (Name.consume_front("convert.to.svbool")) {
+ // 'aarch64.sve.convert.to.svbool'
+ auto *TTy = dyn_cast<TargetExtType>(F->arg_begin()->getType());
+ if (!TTy || TTy->getName() != "aarch64.svcount")
+ return false;
+
+ Intrinsic::ID ID = Intrinsic::aarch64_sve_convert_from_svcount;
+ NewFn = Intrinsic::getOrInsertDeclaration(F->getParent(), ID);
+ return true;
+ }
+
if (Name.consume_front("addqv")) {
// 'aarch64.sve.addqv'.
if (!F->getReturnType()->isFPOrFPVectorTy())
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index fc743256bc1a3..c5af54a97fe32 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -7034,13 +7034,12 @@ SDValue AArch64TargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::aarch64_sve_dupq_lane:
return LowerDUPQLane(Op, DAG);
case Intrinsic::aarch64_sve_convert_from_svbool:
- if (Op.getValueType() == MVT::aarch64svcount)
- return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Op.getOperand(1));
return getSVEPredicateBitCast(Op.getValueType(), Op.getOperand(1), DAG);
case Intrinsic::aarch64_sve_convert_to_svbool:
- if (Op.getOperand(1).getValueType() == MVT::aarch64svcount)
- return DAG.getNode(ISD::BITCAST, DL, MVT::nxv16i1, Op.getOperand(1));
return getSVEPredicateBitCast(MVT::nxv16i1, Op.getOperand(1), DAG);
+ case Intrinsic::aarch64_sve_convert_from_svcount:
+ case Intrinsic::aarch64_sve_convert_to_svcount:
+ return DAG.getNode(ISD::BITCAST, DL, Op.getValueType(), Op.getOperand(1));
case Intrinsic::aarch64_sve_fneg:
return DAG.getNode(AArch64ISD::FNEG_MERGE_PASSTHRU, DL, Op.getValueType(),
Op.getOperand(2), Op.getOperand(3), Op.getOperand(1));
diff --git a/llvm/test/Bitcode/upgrade-aarch64-sve-intrinsics.ll b/llvm/test/Bitcode/upgrade-aarch64-sve-intrinsics.ll
index 832c2c4e072f4..7be91c47b1e2d 100644
--- a/llvm/test/Bitcode/upgrade-aarch64-sve-intrinsics.ll
+++ b/llvm/test/Bitcode/upgrade-aarch64-sve-intrinsics.ll
@@ -207,6 +207,24 @@ define <vscale x 4 x float> @bfmmla_f32(<vscale x 4 x float> %a, <vscale x 8 x b
ret <vscale x 4 x float> %out
}
+declare target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1>)
+define target("aarch64.svcount") @convert_svbool_to_svcount(<vscale x 16 x i1> %pg) "target-features"="+sme2" {
+; CHECK-LABEL: @convert_svbool_to_svcount
+; CHECK: %out = call target("aarch64.svcount") @llvm.aarch64.sve.convert.to.svcount(<vscale x 16 x i1> %pg)
+; CHECK-NEXT: ret target("aarch64.svcount") %out
+ %out = call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1> %pg)
+ ret target("aarch64.svcount") %out
+}
+
+declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount"))
+define <vscale x 16 x i1> @convert_svcount_svbool(target("aarch64.svcount") %pg) "target-features"="+sme2" {
+; CHECK-LABEL: @convert_svcount_svbool
+; CHECK: %out = call <vscale x 16 x i1> @llvm.aarch64.sve.convert.from.svcount(target("aarch64.svcount") %pg)
+; CHECK-NEXT: ret <vscale x 16 x i1> %out
+ %out = call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") %pg)
+ ret <vscale x 16 x i1> %out
+}
+
declare <vscale x 32 x i8> @llvm.aarch64.sve.tuple.create2.nxv32i8.nxv16i8(<vscale x 16 x i8>, <vscale x 16 x i8>)
declare <vscale x 32 x i8> @llvm.aarch64.sve.tuple.create2.nxv32i8(<vscale x 16 x i8>, <vscale x 16 x i8>)
declare <vscale x 32 x i8> @llvm.aarch64.sve.tuple.create2(<vscale x 16 x i8>, <vscale x 16 x i8>)
diff --git a/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll b/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll
index 73a8a5e38ddb4..366ec95ebc658 100644
--- a/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll
+++ b/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll
@@ -59,7 +59,7 @@ define <vscale x 16 x i1> @reinterpret_bool_from_svcount(target("aarch64.svcount
; CHECK-LABEL: reinterpret_bool_from_svcount:
; CHECK: // %bb.0:
; CHECK-NEXT: ret
- %out = call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") %pg)
+ %out = call <vscale x 16 x i1> @llvm.aarch64.sve.convert.from.svcount(target("aarch64.svcount") %pg)
ret <vscale x 16 x i1> %out
}
@@ -111,7 +111,7 @@ define target("aarch64.svcount") @reinterpret_bool_to_svcount(<vscale x 16 x i1>
; CHECK-LABEL: reinterpret_bool_to_svcount:
; CHECK: // %bb.0:
; CHECK-NEXT: ret
- %out = call target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1> %pg)
+ %out = call target("aarch64.svcount") @llvm.aarch64.sve.convert.to.svcount(<vscale x 16 x i1> %pg)
ret target("aarch64.svcount") %out
}
@@ -183,22 +183,3 @@ define <vscale x 16 x i1> @reinterpret_scalar_bool_q(i1 %x){
%out = tail call <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1> %.splat)
ret <vscale x 16 x i1> %out
}
-
-
-declare <vscale x 8 x i1> @llvm.aarch64.sve.ptrue.nxv8i1(i32 immarg)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.ptrue.nxv16i1(i32 immarg)
-declare <vscale x 8 x i1> @llvm.aarch64.sve.cmpgt.nxv8i16(<vscale x 8 x i1>, <vscale x 8 x i16>, <vscale x 8 x i16>)
-
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv16i1(<vscale x 16 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv8i1(<vscale x 8 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv4i1(<vscale x 4 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv2i1(<vscale x 2 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.nxv1i1(<vscale x 1 x i1>)
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount"))
-
-declare <vscale x 16 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv16i1(<vscale x 16 x i1>)
-declare <vscale x 8 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv8i1(<vscale x 16 x i1>)
-declare <vscale x 4 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv4i1(<vscale x 16 x i1>)
-declare <vscale x 2 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv2i1(<vscale x 16 x i1>)
-declare <vscale x 1 x i1> @llvm.aarch64.sve.convert.from.svbool.nxv1i1(<vscale x 16 x i1>)
-declare target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt(<vscale x 16 x i1>)
More information about the llvm-commits
mailing list