Skip to content

Commit

Permalink
[libc] Add differential quality and perf analysis targets for sinf an…
Browse files Browse the repository at this point in the history
…d cosf.

 Infrastructure needed for setting up the diff binaries has been added.
 Along the way, an exhaustive test for sinf and cosf have also been added.

Reviewed By: lntue

Differential Revision: https://reviews.llvm.org/D101276
  • Loading branch information
Siva Chandra Reddy committed Apr 26, 2021
1 parent 51b4610 commit c6aa206
Show file tree
Hide file tree
Showing 16 changed files with 438 additions and 3 deletions.
1 change: 1 addition & 0 deletions libc/test/src/math/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1134,3 +1134,4 @@ add_fp_unittest(

add_subdirectory(generic)
add_subdirectory(exhaustive)
add_subdirectory(differential_testing)
108 changes: 108 additions & 0 deletions libc/test/src/math/differential_testing/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@

function(add_diff_binary target_name)
cmake_parse_arguments(
"DIFF"
"" # No optional arguments
"SUITE" # Single value arguments
"SRCS;HDRS;DEPENDS;COMPILE_OPTIONS" # Multi-value arguments
${ARGN}
)
if(NOT DIFF_SRCS)
message(FATAL_ERROR "'add_diff_binary' target requires a SRCS list of .cpp "
"files.")
endif()
if(NOT DIFF_DEPENDS)
message(FATAL_ERROR "'add_diff_binary' target requires a DEPENDS list of "
"'add_entrypoint_object' targets.")
endif()

get_fq_target_name(${target_name} fq_target_name)
get_fq_deps_list(fq_deps_list ${DIFF_DEPENDS})
get_object_files_for_test(
link_object_files skipped_entrypoints_list ${fq_deps_list})
if(skipped_entrypoints_list)
set(msg "Will not build ${fq_target_name} as it has missing deps: "
"${skipped_entrypoints_list}.")
message(STATUS ${msg})
return()
endif()

add_executable(
${fq_target_name}
EXCLUDE_FROM_ALL
${DIFF_SRCS}
${DIFF_HDRS}
)
target_include_directories(
${fq_target_name}
PRIVATE
${LIBC_SOURCE_DIR}
${LIBC_BUILD_DIR}
${LIBC_BUILD_DIR}/include
)
if(DIFF_COMPILE_OPTIONS)
target_compile_options(
${fq_target_name}
PRIVATE ${DIFF_COMPILE_OPTIONS}
)
endif()

target_link_libraries(
${fq_target_name}
PRIVATE ${link_object_files} libc_test_utils)

set_target_properties(${fq_target_name}
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})

add_dependencies(
${fq_target_name}
libc.utils.FPUtil.fputil
${fq_deps_list}
)
endfunction()

add_header_library(
single_input_single_output_diff
HDRS
SingleInputSingleOutputDiff.h
)

add_diff_binary(
sinf_diff
SRCS
sinf_diff.cpp
DEPENDS
.single_input_single_output_diff
libc.src.math.sinf
)

add_diff_binary(
sinf_perf
SRCS
sinf_perf.cpp
DEPENDS
.single_input_single_output_diff
libc.src.math.sinf
COMPILE_OPTIONS
-fno-builtin
)

add_diff_binary(
cosf_diff
SRCS
cosf_diff.cpp
DEPENDS
.single_input_single_output_diff
libc.src.math.cosf
)

add_diff_binary(
cosf_perf
SRCS
cosf_perf.cpp
DEPENDS
.single_input_single_output_diff
libc.src.math.cosf
COMPILE_OPTIONS
-fno-builtin
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
//===-- Common utility class for differential analysis --------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "utils/FPUtil/FPBits.h"
#include "utils/testutils/StreamWrapper.h"
#include "utils/testutils/Timer.h"

namespace __llvm_libc {
namespace testing {

template <typename T> class SingleInputSingleOutputDiff {
using FPBits = fputil::FPBits<T>;
using UIntType = typename FPBits::UIntType;
static constexpr UIntType MSBit = UIntType(1) << (8 * sizeof(UIntType) - 1);
static constexpr UIntType UIntMax = (MSBit - 1) + MSBit;

public:
typedef T Func(T);

static void runDiff(Func myFunc, Func otherFunc, const char *logFile) {
UIntType diffCount = 0;
testutils::OutputFileStream log(logFile);
log << "Starting diff for values from 0 to " << UIntMax << '\n'
<< "Only differing results will be logged.\n\n";
for (UIntType bits = 0;; ++bits) {
T x = T(FPBits(bits));
T myResult = myFunc(x);
T otherResult = otherFunc(x);
UIntType myBits = FPBits(myResult).uintval();
UIntType otherBits = FPBits(otherResult).uintval();
if (myBits != otherBits) {
++diffCount;
log << " Input: " << bits << " (" << x << ")\n"
<< " My result: " << myBits << " (" << myResult << ")\n"
<< "Other result: " << otherBits << " (" << otherResult << ")\n"
<< '\n';
}
if (bits == UIntMax)
break;
}
log << "Total number of differing results: " << diffCount << '\n';
}

static void runPerf(Func myFunc, Func otherFunc, const char *logFile) {
auto runner = [](Func func) {
volatile T result;
for (UIntType bits = 0;; ++bits) {
T x = T(FPBits(bits));
result = func(x);
if (bits == UIntMax)
break;
}
};

testutils::OutputFileStream log(logFile);
Timer timer;
timer.start();
runner(myFunc);
timer.stop();
log << " Run time of my function: " << timer.nanoseconds() << " ns \n";

timer.start();
runner(otherFunc);
timer.stop();
log << "Run time of other function: " << timer.nanoseconds() << " ns \n";
}
};

} // namespace testing
} // namespace __llvm_libc

#define SINGLE_INPUT_SINGLE_OUTPUT_DIFF(T, myFunc, otherFunc, filename) \
int main() { \
__llvm_libc::testing::SingleInputSingleOutputDiff<T>::runDiff( \
&myFunc, &otherFunc, filename); \
return 0; \
}

#define SINGLE_INPUT_SINGLE_OUTPUT_PERF(T, myFunc, otherFunc, filename) \
int main() { \
__llvm_libc::testing::SingleInputSingleOutputDiff<T>::runPerf( \
&myFunc, &otherFunc, filename); \
return 0; \
}
16 changes: 16 additions & 0 deletions libc/test/src/math/differential_testing/cosf_diff.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//===-- Differential test for cosf ----------------------------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "SingleInputSingleOutputDiff.h"

#include "src/math/cosf.h"

#include <math.h>

SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, __llvm_libc::cosf, ::cosf,
"cosf_diff.log")
16 changes: 16 additions & 0 deletions libc/test/src/math/differential_testing/cosf_perf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//===-- Differential test for cosf ----------------------------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "SingleInputSingleOutputDiff.h"

#include "src/math/cosf.h"

#include <math.h>

SINGLE_INPUT_SINGLE_OUTPUT_PERF(float, __llvm_libc::cosf, ::cosf,
"cosf_perf.log")
16 changes: 16 additions & 0 deletions libc/test/src/math/differential_testing/sinf_diff.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//===-- Differential test for sinf ----------------------------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "SingleInputSingleOutputDiff.h"

#include "src/math/sinf.h"

#include <math.h>

SINGLE_INPUT_SINGLE_OUTPUT_DIFF(float, __llvm_libc::sinf, ::sinf,
"sinf_diff.log")
16 changes: 16 additions & 0 deletions libc/test/src/math/differential_testing/sinf_perf.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//===-- Differential test for sinf ----------------------------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "SingleInputSingleOutputDiff.h"

#include "src/math/sinf.h"

#include <math.h>

SINGLE_INPUT_SINGLE_OUTPUT_PERF(float, __llvm_libc::sinf, ::sinf,
"sinf_perf.log")
26 changes: 26 additions & 0 deletions libc/test/src/math/exhaustive/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,29 @@ add_fp_unittest(
libc.src.math.sqrtf
libc.utils.FPUtil.fputil
)

add_fp_unittest(
sinf_test
NEED_MPFR
SUITE
libc_math_exhaustive_tests
SRCS
sinf_test.cpp
DEPENDS
libc.include.math
libc.src.math.sinf
libc.utils.FPUtil.fputil
)

add_fp_unittest(
cosf_test
NEED_MPFR
SUITE
libc_math_exhaustive_tests
SRCS
cosf_test.cpp
DEPENDS
libc.include.math
libc.src.math.cosf
libc.utils.FPUtil.fputil
)
26 changes: 26 additions & 0 deletions libc/test/src/math/exhaustive/cosf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Exhaustive test for cosf ------------------------------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "src/math/cosf.h"
#include "utils/FPUtil/FPBits.h"
#include "utils/FPUtil/TestHelpers.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
#include <math.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

namespace mpfr = __llvm_libc::testing::mpfr;

TEST(LlvmLibccosffExhaustiveTest, AllValues) {
uint32_t bits = 0;
do {
FPBits xbits(bits);
float x = float(xbits);
ASSERT_MPFR_MATCH(mpfr::Operation::Cos, x, __llvm_libc::cosf(x), 1.0);
} while (bits++ < 0xffff'ffffU);
}
26 changes: 26 additions & 0 deletions libc/test/src/math/exhaustive/sinf_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- Exhaustive test for sinf ------------------------------------------===//
//
// Part of the LLVM Project, 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
//
//===----------------------------------------------------------------------===//

#include "src/math/sinf.h"
#include "utils/FPUtil/FPBits.h"
#include "utils/FPUtil/TestHelpers.h"
#include "utils/MPFRWrapper/MPFRUtils.h"
#include <math.h>

using FPBits = __llvm_libc::fputil::FPBits<float>;

namespace mpfr = __llvm_libc::testing::mpfr;

TEST(LlvmLibcsinffExhaustiveTest, AllValues) {
uint32_t bits = 0;
do {
FPBits xbits(bits);
float x = float(xbits);
ASSERT_MPFR_MATCH(mpfr::Operation::Sin, x, __llvm_libc::sinf(x), 1.0);
} while (bits++ < 0xffff'ffffU);
}
6 changes: 3 additions & 3 deletions libc/test/src/math/exhaustive/sqrtf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ namespace mpfr = __llvm_libc::testing::mpfr;
TEST(LlvmLibcSqrtfExhaustiveTest, AllValues) {
uint32_t bits = 0;
do {
FPBits x(bits);
ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, float(x), __llvm_libc::sqrtf(x),
0.5);
FPBits xbits(bits);
float x = float(xbits);
ASSERT_MPFR_MATCH(mpfr::Operation::Sqrt, x, __llvm_libc::sqrtf(x), 0.5);
} while (bits++ < 0xffff'ffffU);
}
2 changes: 2 additions & 0 deletions libc/utils/testutils/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,6 @@ add_llvm_library(
ExecuteFunction.h
${FDReaderFile}
FDReader.h
Timer.h
Timer.cpp
)
Loading

0 comments on commit c6aa206

Please sign in to comment.