Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,16 @@ IF(NOT XNNPACK_USE_SYSTEM_LIBS)
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/kleidiai-download")
SET(KLEIDIAI_SOURCE_DIR "${CMAKE_BINARY_DIR}/kleidiai-source" CACHE STRING "kleidiai source directory")
ENDIF()

IF(XNNPACK_ENABLE_KLEIDIAI AND NOT DEFINED KLEIDIAI_QMX_SOURCE_DIR)
MESSAGE(STATUS "Downloading KleidiAI-QMX to ${CMAKE_BINARY_DIR}/kleidiai-qmx-source (define KLEIDIAI_QMX_SOURCE_DIR to avoid it)")
CONFIGURE_FILE(cmake/DownloadKleidiAI-QMX.cmake "${CMAKE_BINARY_DIR}/kleidiai-qmx-download/CMakeLists.txt")
EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/kleidiai-qmx-download")
EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/kleidiai-qmx-download")
SET(KLEIDIAI_QMX_SOURCE_DIR "${CMAKE_BINARY_DIR}/kleidiai-qmx-source" CACHE STRING "kleidiai QMX source directory")
ENDIF()
ENDIF()

# ---[ XNNPACK library
Expand Down Expand Up @@ -1342,6 +1352,28 @@ IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(xnnpack-base INTERFACE kleidiai)
ENDIF()

# ---[ Configure KleidiAI-QMX
IF(XNNPACK_ENABLE_KLEIDIAI)
IF(NOT TARGET kleidiai_qmx)
IF(NOT XNNPACK_USE_SYSTEM_LIBS)
#SET(KLEIDIAI_BUILD_TESTS OFF CACHE BOOL "")
ADD_SUBDIRECTORY(
"${KLEIDIAI_QMX_SOURCE_DIR}"
"${CMAKE_BINARY_DIR}/kleidiai_qmx")
ELSE()
ADD_LIBRARY(kleidiai_qmx SHARED IMPORTED)
FIND_LIBRARY(KLEIDIAI_QMX_LIBRARY kleidiai_qmx PATHS "${KLEIDIAI_QMX_SOURCE_DIR}/lib")
IF(NOT KLEIDIAI_QMX_LIBRARY)
MESSAGE(FATAL_ERROR "Cannot find KleidiAI QMX")
ENDIF()
TARGET_INCLUDE_DIRECTORIES(kleidiai_qmx INTERFACE "${KLEIDIAI_QMX_SOURCE_DIR}")
SET_PROPERTY(TARGET kleidiai_qmx PROPERTY IMPORTED_LOCATION "${KLEIDIAI_QMX_LIBRARY}")
SET_PROPERTY(TARGET kleidiai_qmx PROPERTY IMPORTED_IMPLIB "${KLEIDIAI_QMX_LIBRARY}")
ENDIF()
ENDIF()
TARGET_LINK_LIBRARIES(xnnpack-base INTERFACE kleidiai_qmx)
ENDIF()

# ---[ XNNPACK unit tests
IF(XNNPACK_BUILD_TESTS)
ADD_SUBDIRECTORY(test)
Expand Down
6 changes: 3 additions & 3 deletions bench/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ ENDIF()
ADD_LIBRARY(packq-benchmark STATIC packq-benchmark.cc)
TARGET_LINK_LIBRARIES(packq-benchmark PRIVATE XNNPACK benchmark::benchmark xnnpack-bench-utils xnnpack-test)
IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(packq-benchmark PRIVATE kleidiai)
TARGET_LINK_LIBRARIES(packq-benchmark PRIVATE kleidiai kleidiai_qmx)
ENDIF()

ADD_LIBRARY(gemm-benchmark STATIC gemm-benchmark.cc)
TARGET_LINK_LIBRARIES(gemm-benchmark PRIVATE XNNPACK benchmark::benchmark xnnpack-bench-utils xnnpack-test)
IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(gemm-benchmark PUBLIC kleidiai)
TARGET_LINK_LIBRARIES(gemm-benchmark PUBLIC kleidiai kleidiai_qmx)
ENDIF()

ADD_SUBDIRECTORY(subgraph)
Expand Down Expand Up @@ -129,5 +129,5 @@ ENDFOREACH()

# Special-case
IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(x8-packq-bench PRIVATE kleidiai)
TARGET_LINK_LIBRARIES(x8-packq-bench PRIVATE kleidiai kleidiai_qmx)
ENDIF()
85 changes: 85 additions & 0 deletions bench/qp8-f32-qc4w-gemm.cc
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,91 @@
#endif // XNN_ENABLE_ARM_SME2 && XNN_ARCH_ARM64


#if XNN_ENABLE_ARM_SME && XNN_ARCH_ARM64
#if XNN_ENABLE_KLEIDIAI
static void qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme(benchmark::State& state, const char* net) {
GEMMBenchmark(state,
xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme,
xnn_init_f32_minmax_scalar_params,
xnn_pack_kai_qs4_weights_and_biases_sme,
xnn_packed_stride_kai_qs4_weights_and_biases_sme,
/*mr=*/[]() -> size_t {
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
if (hardware_config != nullptr && (hardware_config->arch_flags & xnn_arch_arm_sme) == xnn_arch_arm_sme) {
return xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_mr();
} else {
return 0;
}
}
, /*nr=*/[]() -> size_t {
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
if (hardware_config != nullptr && (hardware_config->arch_flags & xnn_arch_arm_sme) == xnn_arch_arm_sme) {
return xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_nr();
} else {
return 0;
}
}
, /*kr=*/4, /*sr=*/1,
/*mr_packed=*/[]() -> size_t {
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
if (hardware_config != nullptr && (hardware_config->arch_flags & xnn_arch_arm_sme) == xnn_arch_arm_sme) {
return xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_mr();
} else {
return 0;
}
}
,
/*arch_flags=*/xnn_arch_arm_sme);
}

BENCHMARK_GEMM(qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme)

static void qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme(benchmark::State& state, const char* net) {
GEMMBenchmark(state,
xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme,
xnn_init_f32_minmax_scalar_params,
xnn_pack_kai_qs4_weights_and_biases_sme,
xnn_packed_stride_kai_qs4_weights_and_biases_sme,
/*mr=*/[]() -> size_t {
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
if (hardware_config != nullptr && (hardware_config->arch_flags & xnn_arch_arm_sme) == xnn_arch_arm_sme) {
return xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_mr();
} else {
return 0;
}
}
, /*nr=*/[]() -> size_t {
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
if (hardware_config != nullptr && (hardware_config->arch_flags & xnn_arch_arm_sme) == xnn_arch_arm_sme) {
return xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_nr();
} else {
return 0;
}
}
, /*kr=*/4, /*sr=*/1,
/*mr_packed=*/[]() -> size_t {
const struct xnn_hardware_config* hardware_config =
xnn_init_hardware_config();
if (hardware_config != nullptr && (hardware_config->arch_flags & xnn_arch_arm_sme) == xnn_arch_arm_sme) {
return xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_mr();
} else {
return 0;
}
}
,
/*arch_flags=*/xnn_arch_arm_sme);
}

BENCHMARK_GEMM(qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme)
#endif // XNN_ENABLE_KLEIDIAI
#endif // XNN_ENABLE_ARM_SME && XNN_ARCH_ARM64


#ifndef XNNPACK_BENCHMARK_NO_MAIN
XNN_BENCHMARK_MAIN();
#endif
31 changes: 31 additions & 0 deletions cmake/DownloadKleidiAI-QMX.cmake
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Copyright (c) Facebook, Inc. and its affiliates.
# All rights reserved.
#
# Copyright 2025 Google LLC
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree.

CMAKE_MINIMUM_REQUIRED(VERSION 3.5 FATAL_ERROR)

PROJECT(kleidiai-qmx-download NONE)

# Set file timestamps to the time of extraction.
IF(POLICY CMP0135)
CMAKE_POLICY(SET CMP0135 NEW)
ENDIF()

# LINT.IfChange
INCLUDE(ExternalProject)
ExternalProject_Add(kleidiai
URL https://github.com/qualcomm/kleidiai/archive/3e605b85be4d3b411011bc8b8d09b12cc663ade3.zip
URL_HASH SHA256=e0ed9626832b3b4dcd061bdf3eaa64a9e2903319c4c834362de9877756056243
SOURCE_DIR "${CMAKE_BINARY_DIR}/kleidiai-qmx-source"
BINARY_DIR "${CMAKE_BINARY_DIR}/kleidiai-qmx"
CONFIGURE_COMMAND ""
PATCH_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
# LINT.ThenChange(../MODULE.bazel:kleidiai)
2 changes: 2 additions & 0 deletions cmake/gen/neonsme_microkernels.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ SET(PROD_NEONSME_MICROKERNEL_SRCS
src/x32-pack-lh/x32-packlh-igemm-neonsme.c
src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-1x64c4-neonsme.c
src/qp8-f32-qc8w-gemm/qp8-f32-qc8w-gemm-minmax-16x64c4-neonsme.c
src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-1x64c4-neonsme.c
src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-16x64c4-neonsme.c
src/x16-pack-lh/x16-packlh-igemm-neonsme.c
src/x16-pack-lh/x16-packlh-neonsme.c
src/x32-pack-lh/x32-packlh-neonsme.c)
Expand Down
17 changes: 16 additions & 1 deletion src/configs/gemm-config.c
Original file line number Diff line number Diff line change
Expand Up @@ -2552,7 +2552,22 @@ static void init_qp8_f32_qc4w_gemm_config(void) {
qp8_f32_qc4w_gemm_config.planes = 2;
qp8_f32_qc4w_gemm_config.mr_packed = mr;
#endif // XNN_ENABLE_ARM_SME2
} else if (XNN_ENABLE_ARM_I8MM && (hardware_config->arch_flags & xnn_arch_arm_neon_i8mm)) {
}else if (XNN_ENABLE_ARM_SME && (hardware_config->arch_flags & xnn_arch_arm_sme)) {
#if XNN_ENABLE_ARM_SME
const size_t mr = xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_mr();
const size_t nr = xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_nr();
qp8_f32_qc4w_gemm_config.minmax.qp8gemm[XNN_MR_TO_INDEX(1)] = XNN_INIT_HMP_QP8GEMM_UKERNEL(xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme);
qp8_f32_qc4w_gemm_config.minmax.qp8gemm[XNN_MR_TO_INDEX(mr)] = XNN_INIT_HMP_QP8GEMM_UKERNEL(xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme);
qp8_f32_qc4w_gemm_config.init.f32 = xnn_init_f32_minmax_scalar_params;
qp8_f32_qc4w_gemm_config.pack_weights_and_biases = xnn_pack_kai_qs4_weights_and_biases_sme;
qp8_f32_qc4w_gemm_config.packed_stride_weights_and_biases = xnn_packed_stride_kai_qs4_weights_and_biases_sme;
qp8_f32_qc4w_gemm_config.mr = mr;
qp8_f32_qc4w_gemm_config.nr = nr;
qp8_f32_qc4w_gemm_config.log2_kr = 2;
qp8_f32_qc4w_gemm_config.planes = 2;
qp8_f32_qc4w_gemm_config.mr_packed = mr;
#endif // XNN_ENABLE_ARM_SME
}else if (XNN_ENABLE_ARM_I8MM && (hardware_config->arch_flags & xnn_arch_arm_neon_i8mm)) {
#if XNN_ENABLE_ARM_I8MM && XNN_ENABLE_ARM_DOTPROD
qp8_f32_qc4w_gemm_config.minmax.qp8gemm[XNN_MR_TO_INDEX(1)] = XNN_INIT_HMP_QP8GEMM_UKERNEL(xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x8c16s2__aarch64_neondot);
qp8_f32_qc4w_gemm_config.minmax.qp8gemm[XNN_MR_TO_INDEX(8)] = XNN_INIT_HMP_QP8GEMM_UKERNEL(xnn_qp8_f32_qc4w_gemm_minmax_ukernel_8x8c16s2__neoni8mm_mstep2);
Expand Down
41 changes: 41 additions & 0 deletions src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-16x64c4-neonsme.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Copyright 2025 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.

#include <stddef.h>

#include "src/xnnpack/microparams.h"

#if XNN_ENABLE_KLEIDIAI
#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4cxp/kai_matmul_clamp_f32_qai8dxp1vlx8_qsi4cxp4vlx8_1vlx4vl_sme1_mopa.h"

size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_mr() {
return kai_get_mr_matmul_clamp_f32_qai8dxp1vlx8_qsi4cxp4vlx8_1vlx4vl_sme1_mopa();
}

size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_nr() {
return kai_get_nr_matmul_clamp_f32_qai8dxp1vlx8_qsi4cxp4vlx8_1vlx4vl_sme1_mopa();
}
#endif // XNN_ENABLE_KLEIDIAI

// Wraps the
// `kai_run_matmul_clamp_f32_qai8dxp1vlx8_qsi4cxp4vlx8_1vlx4vl_sme1_mopa` GEMM
// microkernel with a name that is compatible with our tooling.
void xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme(
size_t m, size_t n, size_t k, const void* lhs_packed,
const void* rhs_packed, float* dst, size_t dst_stride_row,
size_t dst_stride_col,
const struct xnn_f32_minmax_params* minmax_params) {
#if XNN_ENABLE_KLEIDIAI
kai_run_matmul_clamp_f32_qai8dxp1vlx8_qsi4cxp4vlx8_1vlx4vl_sme1_mopa(
m, n, k, lhs_packed, rhs_packed, dst, dst_stride_row,
/*dst_stride_col=*/sizeof(float), minmax_params->scalar.min,
minmax_params->scalar.max);
#else
assert(
"Calling KleidiAI microkernel wrapper, but XNNPACK was compiled without "
"`XNN_ENABLE_KLEIDIAI`." &&
0);
#endif // XNN_ENABLE_KLEIDIAI
}
38 changes: 38 additions & 0 deletions src/qp8-f32-qc4w-gemm/qp8-f32-qc4w-gemm-minmax-1x64c4-neonsme.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2025 Google LLC
//
// This source code is licensed under the BSD-style license found in the
// LICENSE file in the root directory of this source tree.

#include <stddef.h>
#include "src/xnnpack/microparams.h"

#if XNN_ENABLE_KLEIDIAI
#include "kai/ukernels/matmul/matmul_clamp_f32_qai8dxp_qsi4cxp/kai_matmul_clamp_f32_qai8dxp1x4_qsi4cxp4vlx4_1x4vl_sme1_sdot.h"

size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_mr() {
return kai_get_mr_matmul_clamp_f32_qai8dxp1x4_qsi4cxp4vlx4_1x4vl_sme1_sdot();
}

size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_nr() {
return kai_get_nr_matmul_clamp_f32_qai8dxp1x4_qsi4cxp4vlx4_1x4vl_sme1_sdot();
}
#endif // XNN_ENABLE_KLEIDIAI

// Wraps the `kai_run_matmul_clamp_f32_qai8dxp1x4_qsi4cxp4vlx4_1x4vl_sme1_sdot`
// GEMM microkernel with a name that is compatible with our tooling.
void xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme(
size_t m, size_t n, size_t k, const void* lhs_packed,
const void* rhs_packed, float* dst, size_t dst_stride_row,
size_t dst_stride_col,
struct xnn_f32_minmax_params* minmax_params) {
#if XNN_ENABLE_KLEIDIAI
kai_run_matmul_clamp_f32_qai8dxp1x4_qsi4cxp4vlx4_1x4vl_sme1_sdot(
m, n, k, lhs_packed, rhs_packed, dst, dst_stride_row, /*dst_stride_col=*/sizeof(float),
minmax_params->scalar.min, minmax_params->scalar.max);
#else
assert(
"Calling KleidiAI microkernel wrapper, but XNNPACK was compiled without "
"`XNN_ENABLE_KLEIDIAI`." &&
0);
#endif // XNN_ENABLE_KLEIDIAI
}
8 changes: 8 additions & 0 deletions src/xnnpack/gemm.h
Original file line number Diff line number Diff line change
Expand Up @@ -4020,6 +4020,10 @@ size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme2_get_mr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme2_get_nr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme2_get_mr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme2_get_nr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_mr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme_get_nr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_mr();
size_t xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme_get_nr();

#define DECLARE_QP8_F32_QC4W_GEMM_MINMAX_UKERNEL_FUNCTION(fn_name) \
XNN_INTERNAL void fn_name( \
Expand Down Expand Up @@ -4047,6 +4051,10 @@ DECLARE_QP8_F32_QC4W_GEMM_MINMAX_UKERNEL_FUNCTION(
xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme2)
DECLARE_QP8_F32_QC4W_GEMM_MINMAX_UKERNEL_FUNCTION(
xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme2)
DECLARE_QP8_F32_QC4W_GEMM_MINMAX_UKERNEL_FUNCTION(
xnn_qp8_f32_qc4w_gemm_minmax_ukernel_1x64c4__neonsme)
DECLARE_QP8_F32_QC4W_GEMM_MINMAX_UKERNEL_FUNCTION(
xnn_qp8_f32_qc4w_gemm_minmax_ukernel_16x64c4__neonsme)

size_t xnn_qp8_f32_qc8w_gemm_minmax_ukernel_1x64c4__neonsme2_get_mr();
size_t xnn_qp8_f32_qc8w_gemm_minmax_ukernel_1x64c4__neonsme2_get_nr();
Expand Down
6 changes: 3 additions & 3 deletions test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ TARGET_LINK_LIBRARIES(gemm-microkernel-tester PRIVATE xnnpack-test xnnpack-packi
TARGET_LINK_LIBRARIES(gemm-microkernel-tester PRIVATE pthreadpool)
TARGET_LINK_LIBRARIES(gemm-microkernel-tester PUBLIC next-prime)
IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(gemm-microkernel-tester PRIVATE kleidiai)
TARGET_LINK_LIBRARIES(gemm-microkernel-tester PRIVATE kleidiai kleidiai_qmx)
ENDIF()

ADD_LIBRARY(dwconv-microkernel-tester STATIC dwconv-microkernel-tester.cc)
Expand All @@ -82,7 +82,7 @@ TARGET_LINK_LIBRARIES(unary-ops PRIVATE xnnpack-test )
ADD_LIBRARY(packq-microkernel-tester STATIC packq-microkernel-tester.cc)
TARGET_LINK_LIBRARIES(packq-microkernel-tester PRIVATE xnnpack-test pthreadpool)
IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(packq-microkernel-tester PRIVATE kleidiai)
TARGET_LINK_LIBRARIES(packq-microkernel-tester PRIVATE kleidiai kleidiai_qmx)
ENDIF()

ADD_SUBDIRECTORY(operators)
Expand Down Expand Up @@ -440,7 +440,7 @@ ENDIF()

# Special-case
IF(XNNPACK_ENABLE_KLEIDIAI)
TARGET_LINK_LIBRARIES(x8-packq-test PRIVATE kleidiai)
TARGET_LINK_LIBRARIES(x8-packq-test PRIVATE kleidiai kleidiai_qmx)
ENDIF()

ADD_EXECUTABLE(buffer-test buffer.cc)
Expand Down
Loading