blob: d5f7f40e27daadb6e45f2e5f1e7363f14ecabc2c [file] [edit]
//===----------------------------------------------------------------------===//
//
// Shared helpers for libclc execution conformance tests. These kernels are
// launched on-device and report failure by trapping.
//
//===----------------------------------------------------------------------===//
#ifndef LIBCLC_TEST_CONFORMANCE_H
#define LIBCLC_TEST_CONFORMANCE_H
// Yields an input value the compiler cannot optimize out.
#define TEST_INPUT(TYPE, VALUE) \
({ \
volatile TYPE __clc_in = (VALUE); \
__clc_in; \
})
// Check the condition and submit a hardware trap on failure.
#define CHECK(COND) \
do { \
if (!(COND)) \
__builtin_verbose_trap("libclc", "check failed: " #COND); \
} while (0)
#define CHECK_EQ(LHS, RHS) CHECK((LHS) == (RHS))
#define CHECK_NE(LHS, RHS) CHECK((LHS) != (RHS))
#define CHECK_LT(LHS, RHS) CHECK((LHS) < (RHS))
#define CHECK_LE(LHS, RHS) CHECK((LHS) <= (RHS))
#define CHECK_GT(LHS, RHS) CHECK((LHS) > (RHS))
#define CHECK_GE(LHS, RHS) CHECK((LHS) >= (RHS))
// Representable values between X and Y. Does not handle fractional ULP values
// and rounds up instead, not fully accurate for all cases.
static inline uint __clc_test_ulp_f32(float x, float y) {
uint a = as_uint(x), b = as_uint(y);
a = (a >> 31) ? 0x80000000U - (a & 0x7fffffffU) : 0x80000000U + a;
b = (b >> 31) ? 0x80000000U - (b & 0x7fffffffU) : 0x80000000U + b;
return a > b ? a - b : b - a;
}
// The reference must be of the result's own type, or it converts and the
// distance is measured on the wrong grid.
#define CHECK_ULP_F32(GOT, REF, ULPS) \
do { \
_Static_assert(__builtin_types_compatible_p(__typeof__(GOT), float) && \
__builtin_types_compatible_p(__typeof__(REF), float), \
"CHECK_ULP_F32 needs float operands"); \
CHECK(__clc_test_ulp_f32((GOT), (REF)) <= (ULPS)); \
} while (0)
#ifdef __opencl_c_fp64
static inline ulong __clc_test_ulp_f64(double x, double y) {
ulong a = as_ulong(x), b = as_ulong(y);
a = (a >> 63) ? 0x8000000000000000UL - (a & 0x7fffffffffffffffUL)
: 0x8000000000000000UL + a;
b = (b >> 63) ? 0x8000000000000000UL - (b & 0x7fffffffffffffffUL)
: 0x8000000000000000UL + b;
return a > b ? a - b : b - a;
}
#define CHECK_ULP_F64(GOT, REF, ULPS) \
do { \
_Static_assert(__builtin_types_compatible_p(__typeof__(GOT), double) && \
__builtin_types_compatible_p(__typeof__(REF), double), \
"CHECK_ULP_F64 needs double operands"); \
CHECK(__clc_test_ulp_f64((GOT), (REF)) <= (ULPS)); \
} while (0)
#endif
#ifdef cl_khr_fp16
#pragma OPENCL EXTENSION cl_khr_fp16 : enable
static inline ushort __clc_test_ulp_f16(half x, half y) {
ushort a = as_ushort(x), b = as_ushort(y);
a = (a >> 15) ? 0x8000U - (a & 0x7fffU) : 0x8000U + a;
b = (b >> 15) ? 0x8000U - (b & 0x7fffU) : 0x8000U + b;
return a > b ? a - b : b - a;
}
#define CHECK_ULP_F16(GOT, REF, ULPS) \
do { \
_Static_assert(__builtin_types_compatible_p(__typeof__(GOT), half) && \
__builtin_types_compatible_p(__typeof__(REF), half), \
"CHECK_ULP_F16 needs half operands"); \
CHECK(__clc_test_ulp_f16((GOT), (REF)) <= (ULPS)); \
} while (0)
#endif
#endif // LIBCLC_TEST_CONFORMANCE_H