Skip to content

Commit c85da4c

Browse files
Add support for the --test-configs command-line option
1 parent ebb67f4 commit c85da4c

18 files changed

+477
-203
lines changed

offload/unittests/CMakeLists.txt

Lines changed: 14 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -96,56 +96,26 @@ function(add_offload_unittest test_dirname)
9696
endfunction()
9797

9898
function(add_conformance_test test_name)
99-
set(options "")
100-
set(oneValueArgs "")
101-
set(multiValueArgs "SOURCES;PROVIDERS")
102-
cmake_parse_arguments(ARG "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
99+
set(target_name "${test_name}.conformance")
100+
101+
list(TRANSFORM ARGN PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/" OUTPUT_VARIABLE files)
103102

104-
if(NOT ARG_SOURCES)
105-
message(WARNING "Conformance test '${test_name}' must specify at least one source file")
106-
return()
107-
endif()
108-
if(NOT ARG_PROVIDERS)
109-
message(WARNING "Conformance test '${test_name}' must specify at least one provider")
110-
return()
111-
endif()
112103
if(NOT TARGET libc)
113104
message(WARNING "Cannot run conformance tests without the LLVM C library")
114105
return()
115106
endif()
116107

117-
list(TRANSFORM ARG_SOURCES PREPEND "${CMAKE_CURRENT_SOURCE_DIR}/" OUTPUT_VARIABLE files)
118-
add_custom_target(offload.conformance.${test_name})
119-
120-
foreach(provider IN LISTS ARG_PROVIDERS)
121-
set(candidate_platforms ${OFFLOAD_CONFORMANCE_PROVIDER_PLATFORMS_${provider}})
122-
add_custom_target(offload.conformance.${test_name}.${provider})
123-
124-
foreach(platform IN LISTS candidate_platforms)
125-
if(platform IN_LIST OFFLOAD_CONFORMANCE_AVAILABLE_PLATFORMS)
126-
set(target_name "${test_name}.${provider}.${platform}.conformance")
127-
set(target_call "offload.conformance.${test_name}.${provider}.${platform}")
128-
129-
add_executable(${target_name} ${files})
130-
add_dependencies(${target_name} ${provider}.bin)
131-
target_compile_definitions(${target_name}
132-
PRIVATE PROVIDER="${provider}"
133-
PRIVATE PLATFORM="${platform}"
134-
PRIVATE DEVICE_BINARY_DIR="${OFFLOAD_CONFORMANCE_DEVICE_BINARY_DIR}")
135-
target_link_libraries(${target_name} PRIVATE ${PLUGINS_TEST_COMMON} libc)
136-
set_target_properties(${target_name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
137-
138-
add_custom_target(${target_call}
139-
COMMAND $<TARGET_FILE:${target_name}>
140-
DEPENDS ${target_name}
141-
COMMENT "Running conformance test '${test_name}' with '${provider}' on '${platform}'")
142-
143-
add_dependencies(offload.conformance ${target_call})
144-
add_dependencies(offload.conformance.${test_name} ${target_call})
145-
add_dependencies(offload.conformance.${test_name}.${provider} ${target_call})
146-
endif()
147-
endforeach()
148-
endforeach()
108+
add_executable(${target_name} ${files})
109+
add_dependencies(${target_name} conformance_device_binaries)
110+
target_compile_definitions(${target_name}
111+
PRIVATE DEVICE_BINARY_DIR="${OFFLOAD_CONFORMANCE_DEVICE_BINARY_DIR}")
112+
target_link_libraries(${target_name} PRIVATE ${PLUGINS_TEST_COMMON} libc)
113+
set_target_properties(${target_name} PROPERTIES EXCLUDE_FROM_ALL TRUE)
114+
115+
add_custom_target(offload.conformance.${test_name}
116+
COMMAND $<TARGET_FILE:${target_name}>
117+
DEPENDS ${target_name})
118+
add_dependencies(offload.conformance offload.conformance.${test_name})
149119
endfunction()
150120

151121
set(OFFLOAD_TESTS_FORCE_NVPTX_ARCH "" CACHE STRING

offload/unittests/Conformance/CMakeLists.txt

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,6 @@ add_custom_target(offload.conformance)
22

33
set(PLUGINS_TEST_COMMON MathTest)
44

5-
set(OFFLOAD_CONFORMANCE_PROVIDER_PLATFORMS_llvm-libm "cuda;amdgpu")
6-
set(OFFLOAD_CONFORMANCE_PROVIDER_PLATFORMS_cuda-math "cuda")
7-
set(OFFLOAD_CONFORMANCE_PROVIDER_PLATFORMS_hip-math "amdgpu")
8-
9-
set(OFFLOAD_CONFORMANCE_AVAILABLE_PLATFORMS "")
10-
11-
if("cuda" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
12-
find_package(CUDAToolkit QUIET)
13-
if(PLATFORM_HAS_NVPTX AND CUDAToolkit_FOUND)
14-
list(APPEND OFFLOAD_CONFORMANCE_AVAILABLE_PLATFORMS "cuda")
15-
endif()
16-
endif()
17-
if("amdgpu" IN_LIST LIBOMPTARGET_PLUGINS_TO_BUILD)
18-
if(PLATFORM_HAS_AMDGPU)
19-
list(APPEND OFFLOAD_CONFORMANCE_AVAILABLE_PLATFORMS "amdgpu")
20-
endif()
21-
endif()
22-
235
add_subdirectory(device_code)
246
add_subdirectory(lib)
257
add_subdirectory(tests)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
add_offload_test_device_code(LLVMLibm.c llvm-libm -stdlib -fno-builtin)
22

3+
add_custom_target(conformance_device_binaries DEPENDS llvm-libm.bin)
34
set(OFFLOAD_CONFORMANCE_DEVICE_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR} PARENT_SCOPE)
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// This file contains the definition of custom command-line argument parsers
11+
/// using llvm::cl.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef MATHTEST_COMMANDLINE_HPP
16+
#define MATHTEST_COMMANDLINE_HPP
17+
18+
#include "mathtest/TestConfig.hpp"
19+
20+
#include "llvm/ADT/STLExtras.h"
21+
#include "llvm/ADT/SmallVector.h"
22+
#include "llvm/ADT/StringRef.h"
23+
#include "llvm/Support/CommandLine.h"
24+
25+
#include <string>
26+
27+
namespace llvm {
28+
namespace cl {
29+
30+
struct TestConfigsArg {
31+
enum class Mode { Default, All, Explicit } Mode = Mode::Default;
32+
llvm::SmallVector<mathtest::TestConfig, 4> Explicit;
33+
};
34+
35+
template <> class parser<TestConfigsArg> : public basic_parser<TestConfigsArg> {
36+
public:
37+
parser(Option &O) : basic_parser<TestConfigsArg>(O) {}
38+
39+
static bool isAllowed(const mathtest::TestConfig &Config) {
40+
static const llvm::SmallVector<mathtest::TestConfig, 4> &AllTestConfigs =
41+
mathtest::getAllTestConfigs();
42+
43+
return llvm::is_contained(AllTestConfigs, Config);
44+
}
45+
46+
bool parse(Option &O, StringRef ArgName, StringRef ArgValue,
47+
TestConfigsArg &Val) {
48+
ArgValue = ArgValue.trim();
49+
if (ArgValue.empty())
50+
return O.error(
51+
"Expected '" + getValueName() +
52+
"', but got an empty string. Omit the flag to use defaults");
53+
54+
if (ArgValue.equals_insensitive("all")) {
55+
Val.Mode = TestConfigsArg::Mode::All;
56+
return false;
57+
}
58+
59+
llvm::SmallVector<StringRef, 8> Pairs;
60+
ArgValue.split(Pairs, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
61+
62+
Val.Mode = TestConfigsArg::Mode::Explicit;
63+
Val.Explicit.clear();
64+
65+
for (StringRef Pair : Pairs) {
66+
size_t Pos = Pair.find(':');
67+
if (Pos == StringRef::npos)
68+
return O.error("Expected '<provider>:<platform>', got '" + Pair + "'");
69+
70+
StringRef Provider = Pair.take_front(Pos);
71+
StringRef Platform = Pair.drop_front(Pos + 1);
72+
mathtest::TestConfig Config = {Provider.str(), Platform.str()};
73+
if (!isAllowed(Config))
74+
return O.error("Invalid pair '" + Pair + "'");
75+
76+
Val.Explicit.push_back(Config);
77+
}
78+
79+
return false;
80+
}
81+
82+
StringRef getValueName() const override {
83+
return "all|provider:platform[,provider:platform...]";
84+
}
85+
86+
void printOptionDiff(const Option &O, const TestConfigsArg &V, OptVal Default,
87+
size_t GlobalWidth) const {
88+
printOptionNoValue(O, GlobalWidth);
89+
}
90+
};
91+
} // namespace cl
92+
} // namespace llvm
93+
94+
#endif // MATHTEST_COMMANDLINE_HPP
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
///
9+
/// \file
10+
/// This file contains the declaration of the command-line options and the main
11+
/// interface for selecting test configurations.
12+
///
13+
//===----------------------------------------------------------------------===//
14+
15+
#ifndef MATHTEST_COMMANDLINEEXTRAS_HPP
16+
#define MATHTEST_COMMANDLINEEXTRAS_HPP
17+
18+
#include "mathtest/CommandLine.hpp"
19+
#include "mathtest/TestConfig.hpp"
20+
21+
#include "llvm/ADT/SmallVector.h"
22+
#include "llvm/Support/CommandLine.h"
23+
24+
namespace mathtest {
25+
namespace cl {
26+
27+
extern llvm::cl::opt<bool> IsVerbose;
28+
29+
namespace detail {
30+
31+
extern llvm::cl::opt<llvm::cl::TestConfigsArg> TestConfigsOpt;
32+
} // namespace detail
33+
34+
const llvm::SmallVector<TestConfig, 4> &getTestConfigs();
35+
} // namespace cl
36+
} // namespace mathtest
37+
38+
#endif // MATHTEST_COMMANDLINEEXTRAS_HPP

offload/unittests/Conformance/include/mathtest/DeviceContext.hpp

Lines changed: 11 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
#include <cstddef>
3131
#include <cstdint>
3232
#include <memory>
33-
#include <optional>
3433
#include <tuple>
3534
#include <type_traits>
3635
#include <utility>
@@ -67,47 +66,25 @@ class DeviceContext {
6766
return ManagedBuffer<T>(TypedAddress, Size);
6867
}
6968

70-
[[nodiscard]] std::shared_ptr<DeviceImage>
69+
[[nodiscard]] llvm::Expected<std::shared_ptr<DeviceImage>>
7170
loadBinary(llvm::StringRef Directory, llvm::StringRef BinaryName) const;
7271

73-
[[nodiscard]] std::optional<std::shared_ptr<DeviceImage>>
74-
tryLoadBinary(llvm::StringRef Directory, llvm::StringRef BinaryName) const;
75-
7672
template <typename KernelSignature>
77-
DeviceKernel<KernelSignature>
73+
[[nodiscard]] llvm::Expected<DeviceKernel<KernelSignature>>
7874
getKernel(const std::shared_ptr<DeviceImage> &Image,
79-
llvm::StringRef KernelName) const noexcept {
75+
llvm::StringRef KernelName) const {
8076
assert(Image && "Image provided to getKernel is null");
8177

8278
if (Image->DeviceHandle != DeviceHandle)
83-
FATAL_ERROR("Image provided to getKernel was created for a different "
84-
"device");
79+
return llvm::createStringError(
80+
"Image provided to getKernel was created for a different device");
8581

86-
auto KernelHandleOrErr = getKernelImpl(Image->Handle, KernelName);
82+
auto ExpectedHandle = getKernelHandle(Image->Handle, KernelName);
8783

88-
if (auto Err = KernelHandleOrErr.takeError())
89-
FATAL_ERROR(llvm::toString(std::move(Err)));
84+
if (!ExpectedHandle)
85+
return ExpectedHandle.takeError();
9086

91-
return DeviceKernel<KernelSignature>(Image, *KernelHandleOrErr);
92-
}
93-
94-
template <typename KernelSignature>
95-
[[nodiscard]] std::optional<DeviceKernel<KernelSignature>>
96-
tryGetKernel(const std::shared_ptr<DeviceImage> &Image,
97-
llvm::StringRef KernelName) const noexcept {
98-
assert(Image && "Image provided to getKernel is null");
99-
100-
if (Image->DeviceHandle != DeviceHandle)
101-
return std::nullopt;
102-
103-
auto KernelHandleOrErr = getKernelImpl(Image->Handle, KernelName);
104-
105-
if (auto Err = KernelHandleOrErr.takeError()) {
106-
llvm::consumeError(std::move(Err));
107-
return std::nullopt;
108-
}
109-
110-
return DeviceKernel<KernelSignature>(Image, *KernelHandleOrErr);
87+
return DeviceKernel<KernelSignature>(Image, *ExpectedHandle);
11188
}
11289

11390
template <typename KernelSignature, typename... ArgTypes>
@@ -144,12 +121,9 @@ class DeviceContext {
144121
[[nodiscard]] llvm::StringRef getPlatform() const noexcept;
145122

146123
private:
147-
[[nodiscard]] llvm::Expected<std::shared_ptr<DeviceImage>>
148-
loadBinaryImpl(llvm::StringRef Directory, llvm::StringRef BinaryName) const;
149-
150124
[[nodiscard]] llvm::Expected<ol_symbol_handle_t>
151-
getKernelImpl(ol_program_handle_t ProgramHandle,
152-
llvm::StringRef KernelName) const noexcept;
125+
getKernelHandle(ol_program_handle_t ProgramHandle,
126+
llvm::StringRef KernelName) const noexcept;
153127

154128
void launchKernelImpl(ol_symbol_handle_t KernelHandle, uint32_t NumGroups,
155129
uint32_t GroupSize, const void *KernelArgs,

offload/unittests/Conformance/include/mathtest/ExhaustiveGenerator.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ class [[nodiscard]] ExhaustiveGenerator final
5656
Strides[Index] = Strides[Index + 1] * DimSizes[Index + 1];
5757
}
5858

59+
void reset() noexcept override { NextFlatIndex = 0; }
60+
5961
[[nodiscard]] std::size_t
6062
fill(llvm::MutableArrayRef<InTypes>... Buffers) noexcept override {
6163
const std::array<std::size_t, NumInputs> BufferSizes = {Buffers.size()...};

offload/unittests/Conformance/include/mathtest/GpuMathTest.hpp

Lines changed: 28 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@
2424
#include "mathtest/TestResult.hpp"
2525

2626
#include "llvm/ADT/ArrayRef.h"
27-
#include "llvm/ADT/STLExtras.h"
2827
#include "llvm/ADT/StringRef.h"
28+
#include "llvm/Support/Error.h"
2929

3030
#include <cassert>
3131
#include <cstddef>
@@ -61,12 +61,16 @@ class [[nodiscard]] GpuMathTest final {
6161
using ResultType = ApplyTupleTypes_t<InTypesTuple, PartialResultType>;
6262
using GeneratorType = ApplyTupleTypes_t<InTypesTuple, InputGenerator>;
6363

64-
explicit GpuMathTest(std::shared_ptr<DeviceContext> Context,
65-
llvm::StringRef Provider,
66-
llvm::StringRef DeviceBinaryDir)
67-
: Context(std::move(Context)), Provider(Provider),
68-
Kernel(getKernel(this->Context, Provider, DeviceBinaryDir)) {
69-
assert(this->Context && "Context must not be null");
64+
[[nodiscard]] static llvm::Expected<GpuMathTest>
65+
create(std::shared_ptr<DeviceContext> Context, llvm::StringRef Provider,
66+
llvm::StringRef DeviceBinaryDir) {
67+
assert(Context && "Context must not be null");
68+
69+
auto ExpectedKernel = getKernel(*Context, Provider, DeviceBinaryDir);
70+
if (!ExpectedKernel)
71+
return ExpectedKernel.takeError();
72+
73+
return GpuMathTest(std::move(Context), Provider, *ExpectedKernel);
7074
}
7175

7276
ResultType run(GeneratorType &Generator,
@@ -102,20 +106,26 @@ class [[nodiscard]] GpuMathTest final {
102106
[[nodiscard]] std::string getProvider() const noexcept { return Provider; }
103107

104108
private:
105-
static DeviceKernel<KernelSignature>
106-
getKernel(const std::shared_ptr<DeviceContext> &Context,
107-
llvm::StringRef Provider,
108-
llvm::StringRef DeviceBinaryDir) noexcept {
109-
constexpr llvm::StringRef ValidProviders[] = {"llvm-libm"};
110-
111-
if (llvm::find(ValidProviders, Provider) == std::end(ValidProviders))
112-
FATAL_ERROR(llvm::Twine("Unsupported provider: '") + Provider + "'");
109+
explicit GpuMathTest(std::shared_ptr<DeviceContext> Context,
110+
llvm::StringRef Provider,
111+
DeviceKernel<KernelSignature> Kernel)
112+
: Context(std::move(Context)), Provider(Provider), Kernel(Kernel) {}
113113

114+
static llvm::Expected<DeviceKernel<KernelSignature>>
115+
getKernel(const DeviceContext &Context, llvm::StringRef Provider,
116+
llvm::StringRef DeviceBinaryDir) {
114117
llvm::StringRef BinaryName = Provider;
115-
const auto Image = Context->loadBinary(DeviceBinaryDir, BinaryName);
116118

117-
return Context->getKernel<KernelSignature>(Image,
118-
FunctionConfig::KernelName);
119+
auto ExpectedImage = Context.loadBinary(DeviceBinaryDir, BinaryName);
120+
if (!ExpectedImage)
121+
return ExpectedImage.takeError();
122+
123+
auto ExpectedKernel = Context.getKernel<KernelSignature>(
124+
*ExpectedImage, FunctionConfig::KernelName);
125+
if (!ExpectedKernel)
126+
return ExpectedKernel.takeError();
127+
128+
return *ExpectedKernel;
119129
}
120130

121131
[[nodiscard]] auto createBuffers(std::size_t BufferSize) const {

0 commit comments

Comments
 (0)