Skip to content

Commit

Permalink
Rewrite ABI test logic
Browse files Browse the repository at this point in the history
Refs: gh-191

* Instead of creating full executables, let the compiler produce asm.

* Instead of checking the inside of a function (where it's parameters
  come from and how its return value is returned), look at the asm when
  a function is called.

* Instead of searching for a function name, use inline asm to insert
  begin and end markers. Now that the assembler doesn't run, this can be
  any string.

* Don't rely on optimization anymore, instead explicitly request -O0 to
  see that it works in any case.

Refs: gh-191

Signed-off-by: Matthias Kretz <kretz@kde.org>
  • Loading branch information
mattkretz committed Apr 16, 2018
1 parent 53e12bd commit 721f53f
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 90 deletions.
83 changes: 46 additions & 37 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -311,42 +311,72 @@ if(BUILD_EXTRA_CAST_TESTS)
endif()
vc_add_test(simdarray)

find_program(OBJDUMP objdump)
mark_as_advanced(OBJDUMP)
get_property(_incdirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(incdirs)
foreach(_d ${_incdirs})
list(APPEND incdirs "-I${_d}")
endforeach()

if(OBJDUMP)
separate_arguments(_flags UNIX_COMMAND "${CMAKE_CXX_FLAGS} ${Vc_DEFINITIONS}")
list(APPEND _flags ${Vc_COMPILE_FLAGS})
set(_tmp)
foreach(_f ${_flags})
if(_f MATCHES "^-m" OR _f MATCHES "^/arch:" OR _f MATCHES "^-x")
# nothing
elseif(_f MATCHES "^/[A-Za-z]")
string(SUBSTRING "${_f}" 1 -1 _f)
list(APPEND _tmp "-${_f}")
else()
list(APPEND _tmp "${_f}")
endif()
endforeach()
set(_flags "${_tmp}")

# Test ABI on 64-bit x86: Vector/Mask arguments and return values should pass via registers.
# The 32 bit ABI only allows passing via the stack, so nothing useful to test there.
if(${CMAKE_SYSTEM_PROCESSOR} MATCHES "(x86_64|AMD64|amd64)")
macro(test_abi _target _impl)
set(_test test_${_target})
set(asmfile "${_target}.i")
if("${_impl}" STREQUAL "MIC")
mic_add_executable(${_target} SOURCES abi.cpp LINK_LIBRARIES Vc_MIC COMPILE_FLAGS "-DVc_IMPL=${_impl};${ARGN};-O2")
add_custom_command(OUTPUT ${asmfile}
COMMAND ${MIC_CXX}
${incdirs} ${_flags} -O0 -mmic -DVc_IMPL=${_impl} ${ARGN} -S -o ${asmfile}
${CMAKE_CURRENT_SOURCE_DIR}/abi.cpp
DEPENDS abi.cpp ${CMAKE_SOURCE_DIR}/*/*.h ${CMAKE_SOURCE_DIR}/*/*.tcc
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Build ABI test: ${asmfile}"
VERBATIM
)
else()
add_executable(${_target} EXCLUDE_FROM_ALL abi.cpp)
target_link_libraries(${_target} Vc)
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS "Vc_IMPL=${_impl}")
set_property(TARGET ${_target} APPEND PROPERTY COMPILE_OPTIONS "${ARGN};-O2")
add_custom_command(OUTPUT ${asmfile}
COMMAND ${CMAKE_CXX_COMPILER}
${incdirs} ${_flags} -O0 -DVc_IMPL=${_impl} ${ARGN} -S -o ${asmfile}
${CMAKE_CURRENT_SOURCE_DIR}/abi.cpp
DEPENDS abi.cpp ${CMAKE_SOURCE_DIR}/*/*.h ${CMAKE_SOURCE_DIR}/*/*.tcc
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Build ABI test: ${asmfile}"
VERBATIM
)
endif()
add_custom_target(${_target} DEPENDS ${asmfile})
add_target_property(${_target} LABELS "${_impl}")
add_dependencies(${_impl} ${_target})
add_dependencies(build_tests ${_target})

get_target_property(_exe ${_target} OUTPUT_NAME)
if(NOT _exe)
set(_exe ${_target})
endif()

add_test(NAME ${_test}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMAND ${CMAKE_COMMAND} -DOBJDUMP=${OBJDUMP} -DBINARY=${_exe} -DIMPL=${_impl}
COMMAND ${CMAKE_COMMAND} -DASM=${asmfile} -DIMPL=${_impl}
-DCOMPILER_IS_CLANG=${Vc_COMPILER_IS_CLANG} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${CMAKE_CURRENT_SOURCE_DIR}/abi.cmake
)
set_property(TEST ${_test} PROPERTY LABELS "${_impl}")
add_custom_target(run_${_target}
${CMAKE_COMMAND} -DOBJDUMP=${OBJDUMP} -DBINARY=${_exe} -DIMPL=${_impl}
${CMAKE_COMMAND} -DASM=${asmfile} -DIMPL=${_impl}
-DCOMPILER_IS_CLANG=${Vc_COMPILER_IS_CLANG} -DSYSTEM_NAME=${CMAKE_SYSTEM_NAME}
-P ${CMAKE_CURRENT_SOURCE_DIR}/abi.cmake
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS ${_target}
DEPENDS ${asmfile}
COMMENT "Execute ${_target} test"
VERBATIM
)
Expand Down Expand Up @@ -415,27 +445,6 @@ endif()
vc_add_general_test(alignmentinheritance)
vc_add_general_test(alignedbase)

get_property(_incdirs DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY INCLUDE_DIRECTORIES)
set(incdirs)
foreach(_d ${_incdirs})
list(APPEND incdirs "-I${_d}")
endforeach()

separate_arguments(_flags UNIX_COMMAND "${CMAKE_CXX_FLAGS} ${Vc_DEFINITIONS}")
list(APPEND _flags ${Vc_COMPILE_FLAGS})
set(_tmp)
foreach(_f ${_flags})
if(_f MATCHES "^-m" OR _f MATCHES "^/arch:" OR _f MATCHES "^-x")
# nothing
elseif(_f MATCHES "^/[A-Za-z]")
string(SUBSTRING "${_f}" 1 -1 _f)
list(APPEND _tmp "-${_f}")
else()
list(APPEND _tmp "${_f}")
endif()
endforeach()
set(_flags "${_tmp}")

set(TEST_OPERATOR_FAILURES FALSE CACHE BOOL "Run implicit type conversion operator tests.")
if(TEST_OPERATOR_FAILURES)
find_program(BIN_ENV env)
Expand Down
65 changes: 18 additions & 47 deletions tests/abi.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,48 +2,32 @@
# test Vector<T> ABI
#######################################################################

execute_process(
COMMAND ${OBJDUMP} --no-show-raw-insn -dC -j .text ${BINARY}
COMMAND grep -A3 " <test"
COMMAND sed 1d
COMMAND cut -d: -f2
COMMAND xargs echo
OUTPUT_VARIABLE asm)
string(STRIP "${asm}" asm)
macro(extract_asm marker)
execute_process(
COMMAND grep -A100 ${marker}_start ${ASM}
COMMAND grep -B100 ${marker}_end
COMMAND grep -v -e ${marker}_ -e "#"
OUTPUT_VARIABLE asm)
string(STRIP "${asm}" asm)
string(REPLACE "(%rip)" "" asm "${asm}")
string(REPLACE "\t" " " asm "${asm}")
string(REGEX REPLACE " +" " " asm "${asm}")
endmacro()

if("${asm}" MATCHES "%esp")
set(x86_32 TRUE)
else()
set(x86_32 FALSE)
endif()
set(expect_failure FALSE)
extract_asm(vector_abi)

# Note the regex parts looking for %esp can only match on ia32. (Not sure about x32, though)
# 'retq' on the other hand, can only match on x64
if("${IMPL}" STREQUAL SSE)
set(reference "(^addps %xmm(0,%xmm1 movaps %xmm1,%xmm0 retq|1,%xmm0 retq)|vaddps %xmm(0,%xmm1|1,%xmm0),%xmm0 retq|.*v?movaps 0x[12]4\\(%esp\\),%xmm[01]( | .+ )v?(add|mova)ps 0x[12]4\\(%esp\\),%xmm[01])")
if(x86_32 AND COMPILER_IS_CLANG AND "${SYSTEM_NAME}" STREQUAL "Linux")
set(expect_failure TRUE)
endif()
set(reference "v?movaps a_v, %xmm0.*call .* v?movaps %xmm0, b_v")
elseif("${IMPL}" STREQUAL AVX OR "${IMPL}" STREQUAL AVX2)
set(reference "(^vaddps %ymm(0,%ymm1|1,%ymm0),%ymm0 retq|vmovaps 0x[24]4\\(%esp\\),%ymm[01]( | .+ )v(add|mova)ps 0x[24]4\\(%esp\\),%ymm[01],%ymm)")
if(x86_32 AND COMPILER_IS_CLANG AND "${SYSTEM_NAME}" STREQUAL "Linux")
set(expect_failure TRUE)
endif()
set(reference "vmovaps a_v, %ymm0.*call .* vmovaps %ymm0, b_v")
elseif("${IMPL}" STREQUAL MIC)
set(reference "^vaddps %zmm(0,%zmm1|1,%zmm0),%zmm0 retq")
else()
message(FATAL_ERROR "Unknown IMPL '${IMPL}'")
endif()

if("${asm}" MATCHES "${reference}")
if(expect_failure)
message(FATAL_ERROR "Warning: unexpected pass. The test was flagged as EXPECT_FAILURE but passed instead.")
else()
message("PASS: Vector<T> ABI")
endif()
elseif(expect_failure)
message("Expected Failure.\n'${asm}'\n does not match\n'${reference}'")
message("PASS: Vector<T> ABI")
else()
message(FATAL_ERROR "Failed.\n'${asm}'\n does not match\n'${reference}'")
endif()
Expand All @@ -55,23 +39,10 @@ if("${IMPL}" STREQUAL MIC)
set(reference "%di,.*%si,") # needs to read from %di and %si
endif()

execute_process(
COMMAND ${OBJDUMP} --no-show-raw-insn -dC -j .text ${BINARY}
COMMAND grep -A3 " <mask_test"
COMMAND sed 1d
COMMAND cut -d: -f2
COMMAND xargs echo
OUTPUT_VARIABLE asm)
string(STRIP "${asm}" asm)
string(REPLACE "add" "and" reference "${reference}")
extract_asm(mask_abi)
string(REPLACE "_v" "_m" reference "${reference}")
if("${asm}" MATCHES "${reference}")
if(expect_failure)
message(FATAL_ERROR "Warning: unexpected pass. The test was flagged as EXPECT_FAILURE but passed instead.")
else()
message("PASS: Mask<T> ABI")
endif()
elseif(expect_failure)
message("Expected Failure.\n'${asm}'\n does not match\n'${reference}'")
message("PASS: Mask<T> ABI")
else()
message(FATAL_ERROR "Failed.\n'${asm}'\n does not match\n'${reference}'")
endif()
20 changes: 14 additions & 6 deletions tests/abi.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
#include <Vc/Vc>

Vc::float_v test(Vc::float_v a, Vc::float_v b)
Vc::float_v test_vector_abi(Vc::float_v);
Vc::float_m test_mask_abi(Vc::float_m);

Vc::float_v a_v, b_v;
Vc::float_m a_m, b_m;

void my_test1()
{
return a + b;
asm volatile("vector_abi_start");
b_v = test_vector_abi(a_v);
asm volatile("vector_abi_end");
}

Vc::float_m mask_test(Vc::float_m a, Vc::float_m b)
void my_test2()
{
return a & b;
asm volatile("mask_abi_start");
b_m = test_mask_abi(a_m);
asm volatile("mask_abi_end");
}

int Vc_CDECL main() { return 0; }

0 comments on commit 721f53f

Please sign in to comment.