Skip to content

Commit 20be055

Browse files
committed
Add mechanism for generating LIT tests based on templates.
Add new cmake target check-gen that runs generated LIT tests. Add bf16 and f16 memref print library function. Add floating point value comparison library functions similar to numpy.allclose for comparing f16 vs f32, bf16 vs f32 and f32 vs f32 Add an example template for ReLU operation in Linalg dialect. Template generates f16, bf16 and f32 variants.
1 parent 864e5e7 commit 20be055

File tree

13 files changed

+605
-12
lines changed

13 files changed

+605
-12
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//===- ImexRunnerUtils.h - IMEX Runtime Utilities -------------------------===//
2+
//
3+
// Copyright 2022 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// This file includes runtime functions that can be called from mlir code
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef IMEX_EXECUTIONENGINE_IMEXRUNNERUTILS_H
16+
#define IMEX_EXECUTIONENGINE_IMEXRUNNERUTILS_H
17+
18+
#ifdef _WIN32
19+
#ifndef IMEX_RUNNERUTILS_EXPORT
20+
#ifdef imex_runner_utils_EXPORTS
21+
// We are building this library
22+
#define IMEX_RUNNERUTILS_EXPORT __declspec(dllexport)
23+
#else
24+
// We are using this library
25+
#define IMEX_RUNNERUTILS_EXPORT __declspec(dllimport)
26+
#endif // imex_runner_utils_EXPORTS
27+
#endif // IMEX_RUNNERUTILS_EXPORT
28+
#else
29+
// Non-windows: use visibility attributes.
30+
#define IMEX_RUNNERUTILS_EXPORT __attribute__((visibility("default")))
31+
#endif // _WIN32
32+
33+
#include "mlir/ExecutionEngine/Float16bits.h"
34+
#include "mlir/ExecutionEngine/RunnerUtils.h"
35+
36+
extern "C" IMEX_RUNNERUTILS_EXPORT void
37+
_mlir_ciface_printMemrefBF16(UnrankedMemRefType<bf16> *m);
38+
extern "C" IMEX_RUNNERUTILS_EXPORT void
39+
_mlir_ciface_printMemrefF16(UnrankedMemRefType<f16> *m);
40+
41+
extern "C" IMEX_RUNNERUTILS_EXPORT void printMemrefBF16(int64_t rank,
42+
void *ptr);
43+
extern "C" IMEX_RUNNERUTILS_EXPORT void printMemrefF16(int64_t rank, void *ptr);
44+
45+
extern "C" IMEX_RUNNERUTILS_EXPORT bool
46+
_mlir_ciface_allcloseBF16(UnrankedMemRefType<bf16> *M,
47+
UnrankedMemRefType<float> *N);
48+
extern "C" IMEX_RUNNERUTILS_EXPORT bool
49+
_mlir_ciface_allcloseF16(UnrankedMemRefType<f16> *M,
50+
UnrankedMemRefType<float> *N);
51+
extern "C" IMEX_RUNNERUTILS_EXPORT bool
52+
_mlir_ciface_allcloseF32(UnrankedMemRefType<float> *M,
53+
UnrankedMemRefType<float> *N);
54+
55+
extern "C" IMEX_RUNNERUTILS_EXPORT void
56+
_mlir_ciface_printAllcloseBF16(UnrankedMemRefType<bf16> *M,
57+
UnrankedMemRefType<float> *N);
58+
extern "C" IMEX_RUNNERUTILS_EXPORT void
59+
_mlir_ciface_printAllcloseF16(UnrankedMemRefType<f16> *M,
60+
UnrankedMemRefType<float> *N);
61+
extern "C" IMEX_RUNNERUTILS_EXPORT void
62+
_mlir_ciface_printAllcloseF32(UnrankedMemRefType<float> *M,
63+
UnrankedMemRefType<float> *N);
64+
65+
#endif // IMEX_EXECUTIONENGINE_IMEXRUNNERUTILS_H

lib/ExecutionEngine/CMakeLists.txt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,14 @@ endif()
55
if(IMEX_ENABLE_SYCL_RUNTIME)
66
add_subdirectory(SYCLRUNTIME)
77
endif()
8+
9+
add_mlir_library(imex_runner_utils
10+
SHARED
11+
ImexRunnerUtils.cpp
12+
13+
EXCLUDE_FROM_LIBMLIR
14+
15+
LINK_LIBS PUBLIC
16+
mlir_float16_utils
17+
)
18+
target_compile_definitions(imex_runner_utils PRIVATE imex_runner_utils_EXPORTS)
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
//===- ImexRunnerUtils.cpp - IMEX Runtime Utilities -----------------------===//
2+
//
3+
// Copyright 2022 Intel Corporation
4+
// Part of the IMEX Project, under the Apache License v2.0 with LLVM Exceptions.
5+
// See https://llvm.org/LICENSE.txt for license information.
6+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7+
//
8+
//===----------------------------------------------------------------------===//
9+
///
10+
/// \file
11+
/// This file includes runtime functions that can be called from mlir code
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "imex/ExecutionEngine/ImexRunnerUtils.h"
16+
#include <cmath>
17+
#include <cstdlib>
18+
#include <cstring>
19+
#include <iostream>
20+
#include <string>
21+
22+
// NOLINTBEGIN(*-identifier-naming)
23+
24+
extern "C" void _mlir_ciface_printMemrefBF16(UnrankedMemRefType<bf16> *M) {
25+
impl::printMemRef(*M);
26+
}
27+
28+
extern "C" void _mlir_ciface_printMemrefF16(UnrankedMemRefType<f16> *M) {
29+
impl::printMemRef(*M);
30+
}
31+
32+
extern "C" void printMemrefBF16(int64_t rank, void *ptr) {
33+
UnrankedMemRefType<bf16> descriptor = {rank, ptr};
34+
_mlir_ciface_printMemrefBF16(&descriptor);
35+
}
36+
37+
extern "C" void printMemrefF16(int64_t rank, void *ptr) {
38+
UnrankedMemRefType<f16> descriptor = {rank, ptr};
39+
_mlir_ciface_printMemrefF16(&descriptor);
40+
}
41+
42+
// Copied f16 and bf16 conversion code from
43+
// https://github.com/llvm/llvm-project/blob/main/mlir/lib/ExecutionEngine/Float16bits.cpp
44+
45+
// Union used to make the int/float aliasing explicit so we can access the raw
46+
// bits.
47+
union Float32Bits {
48+
uint32_t u;
49+
float f;
50+
};
51+
52+
const uint32_t kF32MantiBits = 23;
53+
const uint32_t kF32HalfMantiBitDiff = 13;
54+
const uint32_t kF32HalfBitDiff = 16;
55+
const Float32Bits kF32Magic = {113 << kF32MantiBits};
56+
const uint32_t kF32HalfExpAdjust = (127 - 15) << kF32MantiBits;
57+
58+
// Converts the 16 bit representation of a half precision value to a float
59+
// value. This implementation is adapted from Eigen.
60+
static float half2float(uint16_t halfValue) {
61+
const uint32_t shiftedExp =
62+
0x7c00 << kF32HalfMantiBitDiff; // Exponent mask after shift.
63+
64+
// Initialize the float representation with the exponent/mantissa bits.
65+
Float32Bits f = {
66+
static_cast<uint32_t>((halfValue & 0x7fff) << kF32HalfMantiBitDiff)};
67+
const uint32_t exp = shiftedExp & f.u;
68+
f.u += kF32HalfExpAdjust; // Adjust the exponent
69+
70+
// Handle exponent special cases.
71+
if (exp == shiftedExp) {
72+
// Inf/NaN
73+
f.u += kF32HalfExpAdjust;
74+
} else if (exp == 0) {
75+
// Zero/Denormal?
76+
f.u += 1 << kF32MantiBits;
77+
f.f -= kF32Magic.f;
78+
}
79+
80+
f.u |= (halfValue & 0x8000) << kF32HalfBitDiff; // Sign bit.
81+
return f.f;
82+
}
83+
84+
const uint32_t kF32BfMantiBitDiff = 16;
85+
86+
// Converts the 16 bit representation of a bfloat value to a float value. This
87+
// implementation is adapted from Eigen.
88+
static float bfloat2float(uint16_t bfloatBits) {
89+
Float32Bits floatBits;
90+
floatBits.u = static_cast<uint32_t>(bfloatBits) << kF32BfMantiBitDiff;
91+
return floatBits.f;
92+
}
93+
94+
// For information on how to Iterate over UnrankedMemRefType, start with
95+
// https://github.com/llvm/llvm-project/blob/main/mlir/include/mlir/ExecutionEngine/CRunnerUtils.h
96+
extern "C" bool _mlir_ciface_allcloseF16(UnrankedMemRefType<f16> *M,
97+
UnrankedMemRefType<float> *N) {
98+
// atol, rtol values copied from
99+
// https://numpy.org/doc/stable/reference/generated/numpy.allclose.html
100+
// values may need to adjusted in the future
101+
const float atol = 1e-08;
102+
const float rtol = 1e-05;
103+
DynamicMemRefType<f16> DM = DynamicMemRefType<f16>(*M);
104+
DynamicMemRefType<float> DN = DynamicMemRefType<float>(*N);
105+
DynamicMemRefIterator<f16> i = DM.begin();
106+
DynamicMemRefIterator<float> j = DN.begin();
107+
for (; i != DM.end() && j != DN.end(); ++i, ++j) {
108+
f16 lhs = *i;
109+
float rhs = *j;
110+
if (fabs(half2float(lhs.bits) - rhs) > atol + rtol * fabs(rhs)) {
111+
return false;
112+
}
113+
}
114+
return true;
115+
}
116+
117+
extern "C" bool _mlir_ciface_allcloseBF16(UnrankedMemRefType<bf16> *M,
118+
UnrankedMemRefType<float> *N) {
119+
// atol, rtol values copied from
120+
// https://numpy.org/doc/stable/reference/generated/numpy.allclose.html
121+
// values may need to adjusted in the future
122+
const float atol = 1e-08;
123+
const float rtol = 1e-05;
124+
DynamicMemRefType<bf16> DM = DynamicMemRefType<bf16>(*M);
125+
DynamicMemRefType<float> DN = DynamicMemRefType<float>(*N);
126+
DynamicMemRefIterator<bf16> i = DM.begin();
127+
DynamicMemRefIterator<float> j = DN.begin();
128+
for (; i != DM.end() && j != DN.end(); ++i, ++j) {
129+
bf16 lhs = *i;
130+
float rhs = *j;
131+
if (fabs(bfloat2float(lhs.bits) - rhs) > atol + rtol * fabs(rhs)) {
132+
return false;
133+
}
134+
}
135+
return true;
136+
}
137+
138+
extern "C" bool _mlir_ciface_allcloseF32(UnrankedMemRefType<float> *M,
139+
UnrankedMemRefType<float> *N) {
140+
// atol, rtol values copied from
141+
// https://numpy.org/doc/stable/reference/generated/numpy.allclose.html
142+
// values may need to adjusted in the future
143+
const float atol = 1e-08;
144+
const float rtol = 1e-05;
145+
DynamicMemRefType<float> DM = DynamicMemRefType<float>(*M);
146+
DynamicMemRefType<float> DN = DynamicMemRefType<float>(*N);
147+
DynamicMemRefIterator<float> i = DM.begin();
148+
DynamicMemRefIterator<float> j = DN.begin();
149+
for (; i != DM.end() && j != DN.end(); ++i, ++j) {
150+
float lhs = *i;
151+
float rhs = *j;
152+
if (fabs(lhs - rhs) > atol + rtol * fabs(rhs)) {
153+
return false;
154+
}
155+
}
156+
return true;
157+
}
158+
159+
extern "C" void _mlir_ciface_printAllcloseF16(UnrankedMemRefType<f16> *M,
160+
UnrankedMemRefType<float> *N) {
161+
if (_mlir_ciface_allcloseF16(M, N)) {
162+
std::cout << "[ALLCLOSE: TRUE]\n";
163+
} else {
164+
std::cout << "[ALLCLOSE: FALSE]\n";
165+
}
166+
}
167+
168+
extern "C" void _mlir_ciface_printAllcloseBF16(UnrankedMemRefType<bf16> *M,
169+
UnrankedMemRefType<float> *N) {
170+
if (_mlir_ciface_allcloseBF16(M, N)) {
171+
std::cout << "[ALLCLOSE: TRUE]\n";
172+
} else {
173+
std::cout << "[ALLCLOSE: FALSE]\n";
174+
}
175+
}
176+
177+
extern "C" void _mlir_ciface_printAllcloseF32(UnrankedMemRefType<float> *M,
178+
UnrankedMemRefType<float> *N) {
179+
if (_mlir_ciface_allcloseF32(M, N)) {
180+
std::cout << "[ALLCLOSE: TRUE]\n";
181+
} else {
182+
std::cout << "[ALLCLOSE: FALSE]\n";
183+
}
184+
}
185+
186+
// NOLINTEND(*-identifier-naming)

test/CMakeLists.txt

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,3 @@
1-
configure_lit_site_cfg(
2-
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
3-
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
4-
MAIN_CONFIG
5-
${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py
6-
)
7-
81
if(WIN32)
92
set(MLIR_RUNNER_UTILS_DIR ${LLVM_BINARY_DIR}/bin)
103
else()
@@ -16,6 +9,7 @@ set(IMEX_TEST_DEPENDS
169
mlir-cpu-runner
1710
mlir_c_runner_utils
1811
mlir_runner_utils
12+
imex_runner_utils
1913
)
2014

2115
if(IMEX_ENABLE_VULKAN_RUNNER)
@@ -37,24 +31,28 @@ if(IMEX_ENABLE_L0_RUNTIME)
3731
)
3832
endif()
3933

34+
# "Gen" is the root of all generated test cases
35+
add_subdirectory(Gen)
36+
37+
set(IMEX_LIT_CFG_PY ${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py)
4038
configure_lit_site_cfg(
4139
${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
4240
${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg.py
4341
MAIN_CONFIG
44-
${CMAKE_CURRENT_SOURCE_DIR}/lit.cfg.py
42+
${IMEX_LIT_CFG_PY}
4543
)
4644

4745
# limit number of workers for lit test when gpu test is enabled
4846
if(IMEX_ENABLE_L0_RUNTIME OR IMEX_ENABLE_SYCL_RUNTIME OR IMEX_ENABLE_VULKAN_RUNNER)
4947
add_lit_testsuite(check-imex "Running the IMEX regression tests"
5048
${CMAKE_CURRENT_BINARY_DIR}
51-
DEPENDS ${IMEX_TEST_DEPENDS}
49+
DEPENDS ${IMEX_TEST_DEPENDS} check-gen
5250
ARGS "--workers=1"
5351
)
5452
else()
5553
add_lit_testsuite(check-imex "Running the IMEX regression tests"
5654
${CMAKE_CURRENT_BINARY_DIR}
57-
DEPENDS ${IMEX_TEST_DEPENDS}
55+
DEPENDS ${IMEX_TEST_DEPENDS} check-gen
5856
)
5957
endif()
6058
set_target_properties(check-imex PROPERTIES FOLDER "Tests")

0 commit comments

Comments
 (0)