| # 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. | |
| # WILL_FAIL: The test will run, but its pass/fail status will be inverted. | |
| # 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;WILL_FAIL" | |
| "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 dimension. | |
| # 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} | |
| WILL_FAIL | |
| ${_RULE_WILL_FAIL} | |
| ) | |
| endfunction() |