blob: 09db2eb0701e0516ccfd7459b5ba481fe7b021d0 [file] [log] [blame]
# Copyright 2021 The IREE Authors
#
# Licensed under the Apache License v2.0 with LLVM Exceptions.
# See https://llvm.org/LICENSE.txt for license information.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
# iree_static_linker_test()
#
# Creates a test test for the statically linked libraries generated by the
# llvm-cpu compiler target backend and executed using the local-sync runtime
# HAL driver.
#
# Parameters:
# NAME: Name of the target
# SRC: mlir source file to be compiled to an IREE module.
# INPUT_TYPE: Module input type, assuming native c/c++ data types
# HAL_TYPE: HAL data type, see runtime/src/iree/hal/buffer_view.h for possible
# options.
# STATIC_LIB_PREFIX: llvm static library prefix.
# ENTRY_FUNCTION: Entry function call.
# EMITC: Uses EmitC to output C code instead of VM bytecode.
# COMPILER_FLAGS: additional flags to pass to the compiler. Bytecode output
# format and backend flags are passed automatically.
# FUNCTION_INPUTS: Module input in the format of mxnxcx<datatype>.
# LABELS: Additional labels to apply to the test. The package path and
# "driver=local-sync" are added automatically.
# TARGET_CPU_FEATURES: If specified, a string passed as argument to
# --iree-llvmcpu-target-cpu-features.
#
# Example:
# iree_static_linker_test(
# NAME
# edge_detection_test
# SRC
# "edge_detection.mlir"
# STATIC_LIB_PREFIX
# edge_detection_linked_llvm_cpu
# ENTRY_FUNCTION
# "edge_detect_sobel_operator"
# FUNCTION_INPUTS
# "1x128x128xf32"
# COMPILER_FLAGS
# "--iree-input-type=stablehlo"
# )
function(iree_static_linker_test)
if(NOT IREE_BUILD_TESTS)
return()
endif()
# See comment in iree_check_test about this condition.
if(NOT IREE_BUILD_COMPILER AND NOT IREE_HOST_BIN_DIR)
return()
endif()
if(NOT (IREE_TARGET_BACKEND_LLVM_CPU OR IREE_HOST_BIN_DIR) OR
NOT IREE_HAL_DRIVER_LOCAL_SYNC)
return()
endif()
cmake_parse_arguments(
_RULE
"EMITC"
"NAME;SRC;DRIVER;STATIC_LIB_PREFIX;ENTRY_FUNCTION;INPUT_TYPE;HAL_TYPE"
"COMPILER_FLAGS;LABELS;TARGET_CPU_FEATURES;FUNCTION_INPUTS"
${ARGN}
)
if(_RULE_EMITC AND
NOT (IREE_OUTPUT_FORMAT_C OR IREE_HOST_BIN_DIR))
return()
endif()
iree_package_name(_PACKAGE_NAME)
iree_package_ns(_PACKAGE_NS)
set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}")
# Set up static library name.
set(_O_FILE_NAME "${_RULE_NAME}.o")
set(_H_FILE_NAME "${_RULE_NAME}.h")
# Set common iree-compile flags
set(_COMPILER_ARGS ${_RULE_COMPILER_FLAGS})
list(APPEND _COMPILER_ARGS "--iree-hal-target-backends=llvm-cpu")
if(_RULE_TARGET_CPU_FEATURES)
list(APPEND _COMPILER_ARGS "--iree-llvmcpu-target-cpu-features=${_RULE_TARGET_CPU_FEATURES}")
else()
list(APPEND _COMPILER_ARGS "--iree-llvmcpu-target-cpu=generic")
endif()
if(_RULE_EMITC)
set(_C_FILE_NAME "${_RULE_NAME}_emitc.h")
iree_c_module(
NAME
${_RULE_NAME}_emitc
SRC
"${_RULE_SRC}"
FLAGS
${_COMPILER_ARGS}
H_FILE_OUTPUT
"${_C_FILE_NAME}"
STATIC_LIB_PATH
"${_O_FILE_NAME}"
NO_RUNTIME
)
else() # bytecode module path
# Generate the embed data with the bytecode module.
set(_MODULE_NAME "${_RULE_NAME}_module")
set(_EMBED_H_FILE_NAME ${_MODULE_NAME}_c.h)
iree_bytecode_module(
NAME
${_MODULE_NAME}
SRC
"${_RULE_SRC}"
FLAGS
${_COMPILER_ARGS}
STATIC_LIB_PATH
"${_O_FILE_NAME}"
C_IDENTIFIER
"${_NAME}"
PUBLIC
)
endif(_RULE_EMITC)
set(_LIB_NAME "${_NAME}_lib")
add_library(${_LIB_NAME}
STATIC
${_O_FILE_NAME}
)
SET_TARGET_PROPERTIES(
${_LIB_NAME}
PROPERTIES
LINKER_LANGUAGE C
)
# If any of these arguments are not specified, only compilation will be
# tested.
if(NOT _RULE_FUNCTION_INPUTS OR
NOT _RULE_ENTRY_FUNCTION OR
NOT _RULE_STATIC_LIB_PREFIX)
return()
endif()
# Set alias for this static library to be used later in the function.
add_library(${_PACKAGE_NS}::${_RULE_NAME}_lib ALIAS ${_LIB_NAME})
# Process module input configs to be used in the c template.
# Example:
# FUNCTION_INPUTS "1x28x28x1xf32"
# _INPUT_NUM 1
# _INPUT_DIM_STR 4
# _INPUT_SIZE_STR 768
# _INPUT_SHAPE_STR of {1, 28, 28, 1},
# FUNCTION_INPUTS "4xf32,f32"
# _INPUT_NUM 2
# _INPUT_DIM_STR 1, 1
# _INPUT_SIZE_STR 4, 1
# _INPUT_SHAPE_STR of {4}, {1},
string(REPLACE "," ";" _INPUTS_LIST "${_RULE_FUNCTION_INPUTS}")
list(LENGTH _INPUTS_LIST _INPUT_NUM)
set(_INPUT_DIM_LIST)
set(_INPUT_SIZE_LIST)
set(_INPUT_SHAPE_STR)
set(_INPUT_DIM_MAX 0)
foreach(_INPUT_ENTRY ${_INPUTS_LIST})
# Separate the function input into shape (m,n,c) and format
string(REPLACE "x" ";" _INPUT_ENTRY_LIST "${_INPUT_ENTRY}")
list(POP_BACK _INPUT_ENTRY_LIST _INPUT_FORMAT)
# Process shape to compute the size (number of elements) and dimention.
# The results are stored into lists to support multiple inputs
if(NOT _INPUT_ENTRY_LIST) # single entry input
set(_INPUT_ENTRY_LIST "1")
endif()
string(REPLACE ";" ", " _INPUT_ENTRY_STR "${_INPUT_ENTRY_LIST}")
set(_INPUT_SHAPE_STR "${_INPUT_SHAPE_STR}\{${_INPUT_ENTRY_STR}\}, ")
list(LENGTH _INPUT_ENTRY_LIST _INPUT_DIM)
list(APPEND _INPUT_DIM_LIST ${_INPUT_DIM})
if(_INPUT_DIM GREATER _INPUT_DIM_MAX)
set(_INPUT_DIM_MAX ${_INPUT_DIM})
endif()
set(_INPUT_SIZE 1)
foreach(_INPUT_DIM_VAL ${_INPUT_ENTRY_LIST})
math(EXPR _INPUT_SIZE "${_INPUT_SIZE} * ${_INPUT_DIM_VAL}")
endforeach()
list(APPEND _INPUT_SIZE_LIST ${_INPUT_SIZE})
endforeach(_INPUT_ENTRY)
string(REPLACE ";" ", " _INPUT_DIM_STR "${_INPUT_DIM_LIST}")
string(REPLACE ";" ", " _INPUT_SIZE_STR "${_INPUT_SIZE_LIST}")
# Process input and HAL data format based on the last input entry.
set(IREE_INPUT_TYPE)
set(IREE_HAL_TYPE)
if("${_INPUT_FORMAT}" STREQUAL "f32")
set(IREE_INPUT_TYPE "float")
set(IREE_HAL_TYPE "IREE_HAL_ELEMENT_TYPE_FLOAT_32")
elseif("${_INPUT_FORMAT}" STREQUAL "i32")
set(IREE_INPUT_TYPE "int32_t")
set(IREE_HAL_TYPE "IREE_HAL_ELEMENT_TYPE_SINT_32")
elseif("${_INPUT_FORMAT}" STREQUAL "i16")
set(IREE_INPUT_TYPE "int16_t")
set(IREE_HAL_TYPE "IREE_HAL_ELEMENT_TYPE_SINT_16")
elseif("${_INPUT_FORMAT}" STREQUAL "i8")
set(IREE_INPUT_TYPE "int8_t")
set(IREE_HAL_TYPE "IREE_HAL_ELEMENT_TYPE_SINT_8")
elseif("${_INPUT_FORMAT}" STREQUAL "ui8")
set(IREE_INPUT_TYPE "uint8_t")
set(IREE_HAL_TYPE "IREE_HAL_ELEMENT_TYPE_UINT_8")
else()
message(SEND_ERROR "Unsupported format ${_INPUT_FORMAT}")
endif()
# Generate the source file.
# TODO(scotttodd): Move to build time instead of configure time?
set(IREE_STATIC_LIB_HDR "\"${_H_FILE_NAME}\"")
set(IREE_STATIC_LIB_QUERY_FN "${_RULE_STATIC_LIB_PREFIX}_library_query")
set(IREE_MODULE_HDR "${_EMBED_H_FILE_NAME}")
set(IREE_MODULE_CREATE_FN "${_NAME}_create\(\)")
set(IREE_EMITC_HDR "${_C_FILE_NAME}")
set(IREE_MODULE_MAIN_FN "\"module.${_RULE_ENTRY_FUNCTION}\"")
set(IREE_INPUT_NUM "${_INPUT_NUM}")
set(IREE_INPUT_DIM_MAX "${_INPUT_DIM_MAX}")
set(IREE_INPUT_DIM_ARR "\{${_INPUT_DIM_STR}\}")
set(IREE_INPUT_SIZE_ARR "\{${_INPUT_SIZE_STR}\}")
set(IREE_INPUT_SHAPE_ARR "\{${_INPUT_SHAPE_STR}\}")
set(IREE_EXE_NAME "\"${_RULE_NAME}\"")
configure_file(
"${IREE_ROOT_DIR}/build_tools/cmake/static_linker_test.c.in"
"${CMAKE_CURRENT_BINARY_DIR}/${_RULE_NAME}.c"
)
iree_cc_binary(
NAME
${_RULE_NAME}_run
SRCS
"${CMAKE_CURRENT_BINARY_DIR}/${_RULE_NAME}.c"
DEPS
::${_RULE_NAME}_lib
iree::runtime
iree::hal::drivers::local_sync::sync_driver
iree::hal::local::loaders::static_library_loader
)
if(_RULE_EMITC)
target_link_libraries(${_NAME}_run
PRIVATE
iree_vm_shims_emitc
${_NAME}_emitc
)
target_compile_definitions(${_NAME}_run
PRIVATE
EMITC_IMPLEMENTATION=\"${_C_FILE_NAME}\"
)
else()
target_link_libraries(${_NAME}_run PRIVATE ${_NAME}_module_c)
endif()
add_dependencies(iree-test-deps "${_NAME}_run")
iree_native_test(
NAME
${_RULE_NAME}
SRC
::${_RULE_NAME}_run
DRIVER
local-sync
LABELS
${_RULE_LABELS}
${_RULE_TARGET_CPU_FEATURES}
)
endfunction()