diff --git a/llvm/include/llvm/IR/IntrinsicsAArch64.td b/llvm/include/llvm/IR/IntrinsicsAArch64.td --- a/llvm/include/llvm/IR/IntrinsicsAArch64.td +++ b/llvm/include/llvm/IR/IntrinsicsAArch64.td @@ -2107,12 +2107,12 @@ // Reinterpreting data // -def int_aarch64_sve_convert_from_svbool : DefaultAttrsIntrinsic<[llvm_anyvector_ty], +def int_aarch64_sve_convert_from_svbool : DefaultAttrsIntrinsic<[llvm_any_ty], [llvm_nxv16i1_ty], [IntrNoMem]>; def int_aarch64_sve_convert_to_svbool : DefaultAttrsIntrinsic<[llvm_nxv16i1_ty], - [llvm_anyvector_ty], + [llvm_any_ty], [IntrNoMem]>; // diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp @@ -5042,8 +5042,12 @@ 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_fneg: return DAG.getNode(AArch64ISD::FNEG_MERGE_PASSTHRU, dl, Op.getValueType(), diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp --- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp +++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp @@ -737,6 +737,11 @@ if (auto BinOpCombine = tryCombineFromSVBoolBinOp(IC, II)) return BinOpCombine; + // Ignore converts to/from svcount_t. + if (isa(II.getArgOperand(0)->getType()) || + isa(II.getType())) + return std::nullopt; + SmallVector CandidatesForRemoval; Value *Cursor = II.getOperand(0), *EarliestReplacement = nullptr; diff --git a/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll b/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll --- a/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll +++ b/llvm/test/CodeGen/AArch64/sve-intrinsics-reinterpret.ll @@ -55,6 +55,14 @@ ret %res } +define @reinterpret_bool_from_svcount(target("aarch64.svcount") %pg) "target-features"="+sme2" { +; CHECK-LABEL: reinterpret_bool_from_svcount: +; CHECK: // %bb.0: +; CHECK-NEXT: ret + %out = call @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount") %pg) + ret %out +} + ; ; Converting from svbool_t ; @@ -99,6 +107,15 @@ ret %out } +define target("aarch64.svcount") @reinterpret_bool_to_svcount( %pg) "target-features"="+sme2" { +; 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( %pg) + ret target("aarch64.svcount") %out +} + + ; Reinterpreting a ptrue should not introduce an `and` instruction. define @reinterpret_ptrue() { ; CHECK-LABEL: reinterpret_ptrue: @@ -142,9 +159,11 @@ declare @llvm.aarch64.sve.convert.to.svbool.nxv4i1() declare @llvm.aarch64.sve.convert.to.svbool.nxv2i1() declare @llvm.aarch64.sve.convert.to.svbool.nxv1i1() +declare @llvm.aarch64.sve.convert.to.svbool.taarch64.svcountt(target("aarch64.svcount")) declare @llvm.aarch64.sve.convert.from.svbool.nxv16i1() declare @llvm.aarch64.sve.convert.from.svbool.nxv8i1() declare @llvm.aarch64.sve.convert.from.svbool.nxv4i1() declare @llvm.aarch64.sve.convert.from.svbool.nxv2i1() declare @llvm.aarch64.sve.convert.from.svbool.nxv1i1() +declare target("aarch64.svcount") @llvm.aarch64.sve.convert.from.svbool.taarch64.svcountt()