1 //===- llvm/unittest/CodeGen/SPIRVAPITest.cpp -----------------------------===//
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
7 //===----------------------------------------------------------------------===//
10 /// Test that SPIR-V Backend provides an API call that translates LLVM IR Module
13 //===----------------------------------------------------------------------===//
15 #include "llvm/AsmParser/Parser.h"
16 #include "llvm/BinaryFormat/Magic.h"
17 #include "llvm/IR/Module.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "gtest/gtest.h"
20 #include <gmock/gmock.h>
24 using ::testing::StartsWith
;
29 SPIRVTranslateModule(Module
*M
, std::string
&SpirvObj
, std::string
&ErrMsg
,
30 const std::vector
<std::string
> &AllowExtNames
,
31 const std::vector
<std::string
> &Opts
);
33 class SPIRVAPITest
: public testing::Test
{
35 bool toSpirv(StringRef Assembly
, std::string
&Result
, std::string
&ErrMsg
,
36 const std::vector
<std::string
> &AllowExtNames
,
37 const std::vector
<std::string
> &Opts
) {
38 SMDiagnostic ParseError
;
39 M
= parseAssemblyString(Assembly
, ParseError
, Context
);
41 ParseError
.print("IR parsing failed: ", errs());
42 report_fatal_error("Can't parse input assembly.");
45 SPIRVTranslateModule(M
.get(), Result
, ErrMsg
, AllowExtNames
, Opts
);
52 std::unique_ptr
<Module
> M
;
54 static constexpr StringRef ExtensionAssembly
= R
"(
55 define dso_local spir_func void @test1() {
57 %res1 = tail call spir_func i32 @_Z26__spirv_GroupBitwiseAndKHR(i32 2, i32 0, i32 0)
61 declare dso_local spir_func i32 @_Z26__spirv_GroupBitwiseAndKHR(i32, i32, i32)
63 static constexpr StringRef OkAssembly
= R
"(
64 %struct = type { [1 x i64] }
66 define spir_kernel void @foo(ptr noundef byval(%struct) %arg) {
68 call spir_func void @bar(<2 x i32> noundef <i32 0, i32 1>)
72 define spir_func void @bar(<2 x i32> noundef) {
79 TEST_F(SPIRVAPITest
, checkTranslateOk
) {
80 StringRef Assemblies
[] = {"", OkAssembly
};
81 // Those command line arguments that overlap with registered by llc/codegen
82 // are to be started with the ' ' symbol.
83 std::vector
<std::string
> SetOfOpts
[] = {
84 {}, {"- mtriple=spirv32-unknown-unknown"}};
85 for (const auto &Opts
: SetOfOpts
) {
86 for (StringRef
&Assembly
: Assemblies
) {
87 std::string Result
, Error
;
88 bool Status
= toSpirv(Assembly
, Result
, Error
, {}, Opts
);
89 EXPECT_TRUE(Status
&& Error
.empty() && !Result
.empty());
90 EXPECT_EQ(identify_magic(Result
), file_magic::spirv_object
);
95 TEST_F(SPIRVAPITest
, checkTranslateError
) {
96 std::string Result
, Error
;
97 bool Status
= toSpirv(OkAssembly
, Result
, Error
, {},
98 {"-mtriple=spirv32-unknown-unknown"});
100 EXPECT_TRUE(Result
.empty());
102 StartsWith("SPIRVTranslateModule: Unknown command line argument "
103 "'-mtriple=spirv32-unknown-unknown'"));
104 Status
= toSpirv(OkAssembly
, Result
, Error
, {}, {"- O 5"});
105 EXPECT_FALSE(Status
);
106 EXPECT_TRUE(Result
.empty());
107 EXPECT_EQ(Error
, "Invalid optimization level!");
110 TEST_F(SPIRVAPITest
, checkTranslateSupportExtensionByOpts
) {
111 std::string Result
, Error
;
112 std::vector
<std::string
> Opts
{
113 "--spirv-ext=+SPV_KHR_uniform_group_instructions"};
114 bool Status
= toSpirv(ExtensionAssembly
, Result
, Error
, {}, Opts
);
115 EXPECT_TRUE(Status
&& Error
.empty() && !Result
.empty());
116 EXPECT_EQ(identify_magic(Result
), file_magic::spirv_object
);
119 TEST_F(SPIRVAPITest
, checkTranslateSupportExtensionByArg
) {
120 std::string Result
, Error
;
121 std::vector
<std::string
> ExtNames
{"SPV_KHR_uniform_group_instructions"};
122 bool Status
= toSpirv(ExtensionAssembly
, Result
, Error
, ExtNames
, {});
123 EXPECT_TRUE(Status
&& Error
.empty() && !Result
.empty());
124 EXPECT_EQ(identify_magic(Result
), file_magic::spirv_object
);
127 TEST_F(SPIRVAPITest
, checkTranslateSupportExtensionByArgList
) {
128 std::string Result
, Error
;
129 std::vector
<std::string
> ExtNames
{"SPV_KHR_subgroup_rotate",
130 "SPV_KHR_uniform_group_instructions",
131 "SPV_KHR_subgroup_rotate"};
132 bool Status
= toSpirv(ExtensionAssembly
, Result
, Error
, ExtNames
, {});
133 EXPECT_TRUE(Status
&& Error
.empty() && !Result
.empty());
134 EXPECT_EQ(identify_magic(Result
), file_magic::spirv_object
);
137 TEST_F(SPIRVAPITest
, checkTranslateAllExtensions
) {
138 std::string Result
, Error
;
139 std::vector
<std::string
> Opts
{"--spirv-ext=all"};
140 bool Status
= toSpirv(ExtensionAssembly
, Result
, Error
, {}, Opts
);
141 EXPECT_TRUE(Status
&& Error
.empty() && !Result
.empty());
142 EXPECT_EQ(identify_magic(Result
), file_magic::spirv_object
);
145 TEST_F(SPIRVAPITest
, checkTranslateUnknownExtensionByArg
) {
146 std::string Result
, Error
;
147 std::vector
<std::string
> ExtNames
{"SPV_XYZ_my_unknown_extension"};
148 bool Status
= toSpirv(ExtensionAssembly
, Result
, Error
, ExtNames
, {});
149 EXPECT_FALSE(Status
);
150 EXPECT_TRUE(Result
.empty());
151 EXPECT_EQ(Error
, "Unknown SPIR-V extension: SPV_XYZ_my_unknown_extension");
154 #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
155 TEST_F(SPIRVAPITest
, checkTranslateExtensionError
) {
156 std::string Result
, Error
;
157 std::vector
<std::string
> Opts
;
158 EXPECT_DEATH_IF_SUPPORTED(
159 { toSpirv(ExtensionAssembly
, Result
, Error
, {}, Opts
); },
160 "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
161 "following SPIR-V extension: SPV_KHR_uniform_group_instructions");
164 TEST_F(SPIRVAPITest
, checkTranslateUnknownExtensionByOpts
) {
165 std::string Result
, Error
;
166 std::vector
<std::string
> Opts
{"--spirv-ext=+SPV_XYZ_my_unknown_extension"};
167 EXPECT_DEATH_IF_SUPPORTED(
168 { toSpirv(ExtensionAssembly
, Result
, Error
, {}, Opts
); },
169 "SPIRVTranslateModule: for the --spirv-ext option: Unknown SPIR-V");
172 TEST_F(SPIRVAPITest
, checkTranslateWrongExtensionByOpts
) {
173 std::string Result
, Error
;
174 std::vector
<std::string
> Opts
{"--spirv-ext=+SPV_KHR_subgroup_rotate"};
175 EXPECT_DEATH_IF_SUPPORTED(
176 { toSpirv(ExtensionAssembly
, Result
, Error
, {}, Opts
); },
177 "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
178 "following SPIR-V extension: SPV_KHR_uniform_group_instructions");
181 TEST_F(SPIRVAPITest
, checkTranslateWrongExtensionByArg
) {
182 std::string Result
, Error
;
183 std::vector
<std::string
> ExtNames
{"SPV_KHR_subgroup_rotate"};
184 EXPECT_DEATH_IF_SUPPORTED(
185 { toSpirv(ExtensionAssembly
, Result
, Error
, ExtNames
, {}); },
186 "LLVM ERROR: __spirv_GroupBitwiseAndKHR: the builtin requires the "
187 "following SPIR-V extension: SPV_KHR_uniform_group_instructions");
191 } // end namespace llvm