diff --git a/compiler-rt/test/CMakeLists.txt b/compiler-rt/test/CMakeLists.txt --- a/compiler-rt/test/CMakeLists.txt +++ b/compiler-rt/test/CMakeLists.txt @@ -85,6 +85,9 @@ if(COMPILER_RT_BUILD_MEMPROF) compiler_rt_test_runtime(memprof) endif() + if(COMPILER_RT_BUILD_MIP) + compiler_rt_test_runtime(mip) + endif() if(COMPILER_RT_BUILD_XRAY) compiler_rt_test_runtime(xray) endif() diff --git a/compiler-rt/test/mip/CMakeLists.txt b/compiler-rt/test/mip/CMakeLists.txt new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/CMakeLists.txt @@ -0,0 +1,32 @@ +set(MIP_LIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) + +set(MIP_TESTSUITES) +set(MIP_TEST_DEPS + clang clang-resource-headers FileCheck count not compiler-rt-headers + llvm-objcopy llvm-objdump llvm-mipdata) + +if(NOT COMPILER_RT_STANDALONE_BUILD AND COMPILER_RT_BUILD_MIP AND + COMPILER_RT_HAS_MIP) + list(APPEND MIP_TEST_DEPS mip) +endif() + +set(MIP_TEST_ARCH ${MIP_SUPPORTED_ARCH}) +if (COMPILER_RT_BUILD_MIP AND COMPILER_RT_HAS_MIP) + foreach(arch ${MIP_TEST_ARCH}) + set(MIP_TEST_TARGET_ARCH ${arch}) + string(TOLOWER "-${arch}-${OS_NAME}" MIP_TEST_CONFIG_SUFFIX) + get_test_cc_for_arch(${arch} MIP_TEST_TARGET_CC MIP_TEST_TARGET_CFLAGS) + string(TOUPPER ${arch} ARCH_UPPER_CASE) + set(CONFIG_NAME ${ARCH_UPPER_CASE}${OS_NAME}Config) + + configure_lit_site_cfg( + ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in + ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}/lit.site.cfg.py) + list(APPEND MIP_TESTSUITES ${CMAKE_CURRENT_BINARY_DIR}/${CONFIG_NAME}) + endforeach() +endif() + +add_lit_testsuite(check-mip "Running the MIP tests" + ${MIP_TESTSUITES} + DEPENDS ${MIP_TEST_DEPS}) +set_target_properties(check-mip PROPERTIES FOLDER "Compiler-RT Misc") diff --git a/compiler-rt/test/mip/Inputs/external-symbols.cpp b/compiler-rt/test/mip/Inputs/external-symbols.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Inputs/external-symbols.cpp @@ -0,0 +1,8 @@ +// CHECK-DAG: {{.*}}/Inputs/external-symbols.cpp:[[@LINE+1]] +static void duplicate_symbol() {} +inline void merged_symbol() {} + +void use_external_symbols() { + (void)duplicate_symbol; + (void)merged_symbol; +} diff --git a/compiler-rt/test/mip/Posix/block-coverage.cpp b/compiler-rt/test/mip/Posix/block-coverage.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Posix/block-coverage.cpp @@ -0,0 +1,29 @@ +// RUN: %clang -fmachine-profile-generate -fmachine-profile-block-coverage -g -o %t.out %s +// RUN: llvm-objcopy -g %t.out %t.stripped +// RUN: llvm-objdump --headers %t.stripped | FileCheck %s --check-prefix SECTIONS +// RUN: llvm-objcopy --dump-section=__llvm_mipmap=%t.mipmap %t.out +// RUN: %llvm_mipdata create -p %t.mip %t.mipmap +// +// RUN: LLVM_MIP_PROFILE_FILENAME=%t.mipraw %run %t.stripped +// RUN: %llvm_mipdata merge -p %t.mip %t.mipraw +// RUN: %llvm_mipdata show -p %t.mip --debug %t.out | FileCheck %s +// +// REQUIRES: built-in-llvm-tree + +bool bar() { return true; } + +// CHECK: main +// CHECK-NEXT: Source Info: [[FILE:.*]]:[[@LINE+5]] +// CHECK-NEXT: Call Count: 1 +// CHECK-NEXT: Order Sum: 1 +// CHECK-NEXT: Block Coverage: +// CHECK-NEXT: HOT HOT COLD HOT +int main() { + if (bar()) { + return 0; + } else { + return 1; + } +} + +// SECTIONS-NOT: __llvm_mipmap diff --git a/compiler-rt/test/mip/Posix/duplicate-symbol.cpp b/compiler-rt/test/mip/Posix/duplicate-symbol.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Posix/duplicate-symbol.cpp @@ -0,0 +1,16 @@ +// RUN: %clang -fmachine-profile-generate -g -o %t.out %s %S/../Inputs/external-symbols.cpp +// RUN: llvm-objcopy --dump-section=__llvm_mipmap=%t.mipmap %t.out +// RUN: %llvm_mipdata create -p %t.mip %t.mipmap +// RUN: %llvm_mipdata show -p %t.mip --debug %t.out -o %t.show +// RUN: FileCheck %s --input-file %t.show +// RUN: FileCheck %S/../Inputs/external-symbols.cpp --input-file %t.show + +// CHECK-DAG: {{.*}}/duplicate-symbol.cpp:[[@LINE+1]] +static void duplicate_symbol() {} +extern void use_external_symbols(); + +int main() { + (void)use_external_symbols; + (void)duplicate_symbol; + return 0; +} diff --git a/compiler-rt/test/mip/Posix/function-coverage.cpp b/compiler-rt/test/mip/Posix/function-coverage.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Posix/function-coverage.cpp @@ -0,0 +1,25 @@ +// RUN: %clang -fmachine-profile-generate -fmachine-profile-function-coverage -g -o %t.out %s +// RUN: llvm-objcopy -g %t.out %t.stripped +// RUN: llvm-objdump --headers %t.stripped | FileCheck %s --check-prefix SECTIONS +// RUN: llvm-objcopy --dump-section=__llvm_mipmap=%t.mipmap %t.out +// RUN: %llvm_mipdata create -p %t.mip %t.mipmap +// +// RUN: LLVM_MIP_PROFILE_FILENAME=%t.mipraw %run %t.stripped +// RUN: %llvm_mipdata merge -p %t.mip %t.mipraw +// RUN: %llvm_mipdata covered -p %t.mip --debug %t.out | FileCheck %s --check-prefixes CHECK,CHECK-MISSING +// +// REQUIRES: built-in-llvm-tree + +void not_called() {} +// CHECK-DAG: called() +void called() {} + +// CHECK-DAG: main +int main() { + called(); + return 0; +} + +// CHECK-MISSING-NOT: not_called() + +// SECTIONS-NOT: __llvm_mipmap diff --git a/compiler-rt/test/mip/Posix/manual-profile-dump.cpp b/compiler-rt/test/mip/Posix/manual-profile-dump.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Posix/manual-profile-dump.cpp @@ -0,0 +1,32 @@ +// RUN: %clang -fmachine-profile-generate -fno-machine-profile-dump -g -o %t.out %s +// RUN: llvm-objcopy -g %t.out %t.stripped +// RUN: llvm-objdump --headers %t.stripped | FileCheck %s --check-prefix SECTIONS +// RUN: llvm-objcopy --dump-section=__llvm_mipmap=%t.mipmap %t.out +// RUN: %llvm_mipdata create -p %t.mip %t.mipmap +// +// RUN: LLVM_MIP_PROFILE_FILENAME=%t.missing.mipraw %run %t.stripped %t.mipraw +// RUN: not test -f %t.missing.mipraw +// RUN: %llvm_mipdata merge -p %t.mip %t.mipraw +// RUN: %llvm_mipdata show -p %t.mip --debug %t.out | FileCheck %s +// +// REQUIRES: built-in-llvm-tree + +extern "C" { +int __llvm_dump_mip_profile_with_filename(const char *Filename); +} + +// CHECK: _Z3foov +// CHECK-NEXT: Source Info: [[FILE:.*]]:[[@LINE+3]] +// CHECK-NEXT: Call Count: 100 +// CHECK-NEXT: Order Sum: 2 +void foo() {} + +// argv[1] holds the filename to dump. +int main(int argc, const char *argv[]) { + for (int i = 0; i < 100; i++) + foo(); + __llvm_dump_mip_profile_with_filename(argv[1]); + return 0; +} + +// SECTIONS-NOT: __llvm_mipmap diff --git a/compiler-rt/test/mip/Posix/merged-symbol.cpp b/compiler-rt/test/mip/Posix/merged-symbol.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Posix/merged-symbol.cpp @@ -0,0 +1,14 @@ +// RUN: %clang -fmachine-profile-generate -g -o %t.out %s %S/../Inputs/external-symbols.cpp +// RUN: llvm-objcopy --dump-section=__llvm_mipmap=%t.mipmap %t.out +// RUN: %llvm_mipdata create -p %t.mip %t.mipmap +// RUN: %llvm_mipdata show -p %t.mip | FileCheck %s + +// CHECK-DAG: _Z20use_external_symbolsv +inline void merged_symbol() {} +extern void use_external_symbols(); + +int main() { + (void)use_external_symbols; + (void)merged_symbol; + return 0; +} diff --git a/compiler-rt/test/mip/Posix/profile.cpp b/compiler-rt/test/mip/Posix/profile.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/Posix/profile.cpp @@ -0,0 +1,33 @@ +// RUN: %clang -fmachine-profile-generate -g -o %t.out %s +// RUN: llvm-objcopy -g %t.out %t.stripped +// RUN: llvm-objdump --headers %t.stripped | FileCheck %s --check-prefix SECTIONS +// RUN: llvm-objcopy --dump-section=__llvm_mipmap=%t.mipmap %t.out +// RUN: %llvm_mipdata create -p %t.mip %t.mipmap +// +// RUN: LLVM_MIP_PROFILE_FILENAME=%t.mipraw %run %t.stripped +// RUN: %llvm_mipdata merge -p %t.mip %t.mipraw +// RUN: %llvm_mipdata show -p %t.mip --debug %t.out | FileCheck %s +// +// REQUIRES: built-in-llvm-tree + +// CHECK: _Z3barv +// CHECK-NEXT: Source Info: [[FILE:.*]]:[[@LINE+3]] +// CHECK-NEXT: Call Count: 2 +// CHECK-NEXT: Order Sum: 2 +void bar() {} + +// CHECK: _Z3foov +// CHECK-NEXT: Source Info: [[FILE]]:[[@LINE+3]] +// CHECK-NEXT: Call Count: 100 +// CHECK-NEXT: Order Sum: 3 +void foo() {} + +int main() { + bar(); + for (int i = 0; i < 100; i++) + foo(); + bar(); + return 0; +} + +// SECTIONS-NOT: __llvm_mipmap diff --git a/compiler-rt/test/mip/lit.cfg.py b/compiler-rt/test/mip/lit.cfg.py new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/lit.cfg.py @@ -0,0 +1,30 @@ +# -*- Python -*- + +import os + +# Setup config name. +config.name = "MIP" + config.name_suffix + +# Setup source root. +config.test_source_root = os.path.dirname(__file__) + +def build_invocation(compile_flags): + return " " + " ".join([config.clang] + compile_flags) + " " + + +# Assume that llvm-mipdata is in the config.llvm_tools_dir. +llvm_mipdata = os.path.join(config.llvm_tools_dir, "llvm-mipdata") + +config.substitutions.append(("%clang ", build_invocation([config.target_cflags]))) +config.substitutions.append( + ("%clangxx ", build_invocation(config.cxx_mode_flags + [config.target_cflags])) +) +config.substitutions.append(("%llvm_mipdata", llvm_mipdata)) + +config.suffixes = [".c", ".cpp"] +config.excludes = ['Inputs'] + +if config.host_os not in ["Darwin", "Linux"]: + config.unsupported = True +elif config.host_arch not in ["x86_64", "aarch64", "arm"]: + config.unsupported = True diff --git a/compiler-rt/test/mip/lit.site.cfg.py.in b/compiler-rt/test/mip/lit.site.cfg.py.in new file mode 100644 --- /dev/null +++ b/compiler-rt/test/mip/lit.site.cfg.py.in @@ -0,0 +1,20 @@ +@LIT_SITE_CFG_IN_HEADER@ + +# Tool-specific config options. +config.name_suffix = "@MIP_TEST_CONFIG_SUFFIX@" +config.mip_lit_source_dir = "@MIP_LIT_SOURCE_DIR@" +config.target_cflags = "@MIP_TEST_TARGET_CFLAGS@" +config.target_arch = "@MIP_TEST_TARGET_ARCH@" +config.built_with_llvm = ("@COMPILER_RT_STANDALONE_BUILD@" != "TRUE") + +# TODO: Look into whether we can run a capability test on the standalone build to +# see whether it can run 'llvm-mipdata --version' instead of turning off tests for a +# standalone build. +if config.built_with_llvm: + config.available_features.add('built-in-llvm-tree') + +# Load common config for all compiler-rt lit tests +lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured") + +# Load tool-specific config that would do the real work. +lit_config.load_config(config, "@CMAKE_CURRENT_SOURCE_DIR@/lit.cfg.py")