[Clang][MIPS] Send correct architecture for MinGW toolchains (#121042)
[llvm-project.git] / llvm / unittests / Target / SPIRV / SPIRVPartialOrderingVisitorTests.cpp
blob95d6c3f5a294082d4241db66a58a7fe4aa5dac43
1 //===- SPIRVPartialOrderingVisitorTests.cpp ----------------------------===//
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 //===----------------------------------------------------------------------===//
9 #include "SPIRVUtils.h"
10 #include "llvm/Analysis/DominanceFrontier.h"
11 #include "llvm/Analysis/PostDominators.h"
12 #include "llvm/AsmParser/Parser.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/IR/LegacyPassManager.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/PassInstrumentation.h"
18 #include "llvm/IR/Type.h"
19 #include "llvm/IR/TypedPointerType.h"
20 #include "llvm/Support/SourceMgr.h"
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include <queue>
26 using namespace llvm;
27 using namespace llvm::SPIRV;
29 class SPIRVPartialOrderingVisitorTest : public testing::Test {
30 protected:
31 void TearDown() override { M.reset(); }
33 void run(StringRef Assembly) {
34 assert(M == nullptr &&
35 "Calling runAnalysis multiple times is unsafe. See getAnalysis().");
37 SMDiagnostic Error;
38 M = parseAssemblyString(Assembly, Error, Context);
39 assert(M && "Bad assembly. Bad test?");
41 llvm::Function *F = M->getFunction("main");
42 Visitor = std::make_unique<PartialOrderingVisitor>(*F);
45 void
46 checkBasicBlockRank(std::vector<std::pair<const char *, size_t>> &&Expected) {
47 llvm::Function *F = M->getFunction("main");
48 auto It = Expected.begin();
49 Visitor->partialOrderVisit(*F->begin(), [&](BasicBlock *BB) {
50 const auto &[Name, Rank] = *It;
51 EXPECT_TRUE(It != Expected.end())
52 << "Unexpected block \"" << BB->getName() << " visited.";
53 EXPECT_TRUE(BB->getName() == Name)
54 << "Error: expected block \"" << Name << "\" got \"" << BB->getName()
55 << "\"";
56 EXPECT_EQ(Rank, Visitor->GetNodeRank(BB))
57 << "Bad rank for BB \"" << BB->getName() << "\"";
58 It++;
59 return true;
60 });
61 ASSERT_TRUE(It == Expected.end())
62 << "Expected block \"" << It->first
63 << "\" but reached the end of the function instead.";
66 protected:
67 LLVMContext Context;
68 std::unique_ptr<Module> M;
69 std::unique_ptr<PartialOrderingVisitor> Visitor;
72 TEST_F(SPIRVPartialOrderingVisitorTest, EmptyFunction) {
73 StringRef Assembly = R"(
74 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
75 ret void
77 )";
79 run(Assembly);
80 checkBasicBlockRank({{"", 0}});
83 TEST_F(SPIRVPartialOrderingVisitorTest, BasicBlockSwap) {
84 StringRef Assembly = R"(
85 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
86 entry:
87 br label %middle
88 exit:
89 ret void
90 middle:
91 br label %exit
93 )";
95 run(Assembly);
96 checkBasicBlockRank({{"entry", 0}, {"middle", 1}, {"exit", 2}});
99 // Skip condition:
100 // +-> A -+
101 // entry -+ +-> C
102 // +------+
103 TEST_F(SPIRVPartialOrderingVisitorTest, SkipCondition) {
104 StringRef Assembly = R"(
105 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
106 entry:
107 %1 = icmp ne i32 0, 0
108 br i1 %1, label %c, label %a
110 ret void
112 br label %c
116 run(Assembly);
117 checkBasicBlockRank({{"entry", 0}, {"a", 1}, {"c", 2}});
120 // Simple loop:
121 // entry -> header <-----------------+
122 // | `-> body -> continue -+
123 // `-> end
124 TEST_F(SPIRVPartialOrderingVisitorTest, LoopOrdering) {
125 StringRef Assembly = R"(
126 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
127 entry:
128 %1 = icmp ne i32 0, 0
129 br label %header
130 end:
131 ret void
132 body:
133 br label %continue
134 continue:
135 br label %header
136 header:
137 br i1 %1, label %body, label %end
141 run(Assembly);
142 checkBasicBlockRank(
143 {{"entry", 0}, {"header", 1}, {"body", 2}, {"continue", 3}, {"end", 4}});
146 // Diamond condition:
147 // +-> A -+
148 // entry -+ +-> C
149 // +-> B -+
151 // A and B order can be flipped with no effect, but it must be remain
152 // deterministic/stable.
153 TEST_F(SPIRVPartialOrderingVisitorTest, DiamondCondition) {
154 StringRef Assembly = R"(
155 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
156 entry:
157 %1 = icmp ne i32 0, 0
158 br i1 %1, label %a, label %b
160 ret void
162 br label %c
164 br label %c
168 run(Assembly);
169 checkBasicBlockRank({{"entry", 0}, {"a", 1}, {"b", 1}, {"c", 2}});
172 // Crossing conditions:
173 // +------+ +-> C -+
174 // +-> A -+ | | |
175 // entry -+ +--_|_-+ +-> E
176 // +-> B -+ | |
177 // +------+----> D -+
179 // A & B have the same rank.
180 // C & D have the same rank, but are after A & B.
181 // E if the last block.
182 TEST_F(SPIRVPartialOrderingVisitorTest, CrossingCondition) {
183 StringRef Assembly = R"(
184 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
185 entry:
186 %1 = icmp ne i32 0, 0
187 br i1 %1, label %a, label %b
189 ret void
191 br label %e
193 br i1 %1, label %d, label %c
195 br label %e
197 br i1 %1, label %c, label %d
201 run(Assembly);
202 checkBasicBlockRank(
203 {{"entry", 0}, {"a", 1}, {"b", 1}, {"c", 2}, {"d", 2}, {"e", 3}});
206 TEST_F(SPIRVPartialOrderingVisitorTest, LoopDiamond) {
207 StringRef Assembly = R"(
208 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
209 entry:
210 %1 = icmp ne i32 0, 0
211 br label %header
212 header:
213 br i1 %1, label %body, label %end
214 body:
215 br i1 %1, label %inside_a, label %break
216 inside_a:
217 br label %inside_b
218 inside_b:
219 br i1 %1, label %inside_c, label %inside_d
220 inside_c:
221 br label %continue
222 inside_d:
223 br label %continue
224 break:
225 br label %end
226 continue:
227 br label %header
228 end:
229 ret void
233 run(Assembly);
234 checkBasicBlockRank({{"entry", 0},
235 {"header", 1},
236 {"body", 2},
237 {"inside_a", 3},
238 {"inside_b", 4},
239 {"inside_c", 5},
240 {"inside_d", 5},
241 {"continue", 6},
242 {"break", 7},
243 {"end", 8}});
246 TEST_F(SPIRVPartialOrderingVisitorTest, LoopNested) {
247 StringRef Assembly = R"(
248 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
249 entry:
250 %1 = icmp ne i32 0, 0
251 br label %a
253 br i1 %1, label %h, label %b
255 br label %c
257 br i1 %1, label %d, label %e
259 br label %g
261 br label %f
263 br label %c
265 br label %a
267 ret void
271 run(Assembly);
272 checkBasicBlockRank({{"entry", 0},
273 {"a", 1},
274 {"b", 2},
275 {"c", 3},
276 {"e", 4},
277 {"f", 5},
278 {"d", 6},
279 {"g", 7},
280 {"h", 8}});
283 TEST_F(SPIRVPartialOrderingVisitorTest, IfNested) {
284 StringRef Assembly = R"(
285 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
286 entry:
287 br i1 true, label %a, label %d
289 br i1 true, label %b, label %c
291 br label %c
293 br label %j
295 br i1 true, label %e, label %f
297 br label %i
299 br i1 true, label %g, label %h
301 br label %h
303 br label %i
305 br label %j
307 ret void
310 run(Assembly);
311 checkBasicBlockRank({{"entry", 0},
312 {"a", 1},
313 {"d", 1},
314 {"b", 2},
315 {"e", 2},
316 {"f", 2},
317 {"c", 3},
318 {"g", 3},
319 {"h", 4},
320 {"i", 5},
321 {"j", 6}});
324 TEST_F(SPIRVPartialOrderingVisitorTest, CheckDeathIrreducible) {
325 StringRef Assembly = R"(
326 define void @main() convergent "hlsl.numthreads"="4,8,16" "hlsl.shader"="compute" {
327 entry:
328 %1 = icmp ne i32 0, 0
329 br label %a
331 br i1 %1, label %a, label %c
333 br label %b
335 br i1 %1, label %b, label %c
339 ASSERT_DEATH(
340 { run(Assembly); },
341 "No valid candidate in the queue. Is the graph reducible?");