1fd4e5da5Sopenharmony_ci// Copyright (c) 2018 Google LLC
2fd4e5da5Sopenharmony_ci//
3fd4e5da5Sopenharmony_ci// Licensed under the Apache License, Version 2.0 (the "License");
4fd4e5da5Sopenharmony_ci// you may not use this file except in compliance with the License.
5fd4e5da5Sopenharmony_ci// You may obtain a copy of the License at
6fd4e5da5Sopenharmony_ci//
7fd4e5da5Sopenharmony_ci//     http://www.apache.org/licenses/LICENSE-2.0
8fd4e5da5Sopenharmony_ci//
9fd4e5da5Sopenharmony_ci// Unless required by applicable law or agreed to in writing, software
10fd4e5da5Sopenharmony_ci// distributed under the License is distributed on an "AS IS" BASIS,
11fd4e5da5Sopenharmony_ci// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12fd4e5da5Sopenharmony_ci// See the License for the specific language governing permissions and
13fd4e5da5Sopenharmony_ci// limitations under the License.
14fd4e5da5Sopenharmony_ci
15fd4e5da5Sopenharmony_ci#include <memory>
16fd4e5da5Sopenharmony_ci#include <vector>
17fd4e5da5Sopenharmony_ci
18fd4e5da5Sopenharmony_ci#include "function_utils.h"
19fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
20fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
21fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h"
22fd4e5da5Sopenharmony_ci#include "source/opt/ir_context.h"
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_cinamespace spvtools {
25fd4e5da5Sopenharmony_cinamespace opt {
26fd4e5da5Sopenharmony_cinamespace {
27fd4e5da5Sopenharmony_ci
28fd4e5da5Sopenharmony_ciusing ::testing::Eq;
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_ciTEST(FunctionTest, HasEarlyReturn) {
31fd4e5da5Sopenharmony_ci  std::string shader = R"(
32fd4e5da5Sopenharmony_ci          OpCapability Shader
33fd4e5da5Sopenharmony_ci     %1 = OpExtInstImport "GLSL.std.450"
34fd4e5da5Sopenharmony_ci          OpMemoryModel Logical GLSL450
35fd4e5da5Sopenharmony_ci          OpEntryPoint Vertex %6 "main"
36fd4e5da5Sopenharmony_ci
37fd4e5da5Sopenharmony_ci; Types
38fd4e5da5Sopenharmony_ci     %2 = OpTypeBool
39fd4e5da5Sopenharmony_ci     %3 = OpTypeVoid
40fd4e5da5Sopenharmony_ci     %4 = OpTypeFunction %3
41fd4e5da5Sopenharmony_ci
42fd4e5da5Sopenharmony_ci; Constants
43fd4e5da5Sopenharmony_ci     %5 = OpConstantTrue %2
44fd4e5da5Sopenharmony_ci
45fd4e5da5Sopenharmony_ci; main function without early return
46fd4e5da5Sopenharmony_ci     %6 = OpFunction %3 None %4
47fd4e5da5Sopenharmony_ci     %7 = OpLabel
48fd4e5da5Sopenharmony_ci          OpBranch %8
49fd4e5da5Sopenharmony_ci     %8 = OpLabel
50fd4e5da5Sopenharmony_ci          OpBranch %9
51fd4e5da5Sopenharmony_ci     %9 = OpLabel
52fd4e5da5Sopenharmony_ci          OpBranch %10
53fd4e5da5Sopenharmony_ci    %10 = OpLabel
54fd4e5da5Sopenharmony_ci          OpReturn
55fd4e5da5Sopenharmony_ci          OpFunctionEnd
56fd4e5da5Sopenharmony_ci
57fd4e5da5Sopenharmony_ci; function with early return
58fd4e5da5Sopenharmony_ci    %11 = OpFunction %3 None %4
59fd4e5da5Sopenharmony_ci    %12 = OpLabel
60fd4e5da5Sopenharmony_ci          OpSelectionMerge %15 None
61fd4e5da5Sopenharmony_ci          OpBranchConditional %5 %13 %14
62fd4e5da5Sopenharmony_ci    %13 = OpLabel
63fd4e5da5Sopenharmony_ci          OpReturn
64fd4e5da5Sopenharmony_ci    %14 = OpLabel
65fd4e5da5Sopenharmony_ci          OpBranch %15
66fd4e5da5Sopenharmony_ci    %15 = OpLabel
67fd4e5da5Sopenharmony_ci          OpReturn
68fd4e5da5Sopenharmony_ci          OpFunctionEnd
69fd4e5da5Sopenharmony_ci  )";
70fd4e5da5Sopenharmony_ci
71fd4e5da5Sopenharmony_ci  const auto context =
72fd4e5da5Sopenharmony_ci      BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, shader,
73fd4e5da5Sopenharmony_ci                  SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
74fd4e5da5Sopenharmony_ci
75fd4e5da5Sopenharmony_ci  // Tests |function| without early return.
76fd4e5da5Sopenharmony_ci  auto* function = spvtest::GetFunction(context->module(), 6);
77fd4e5da5Sopenharmony_ci  ASSERT_FALSE(function->HasEarlyReturn());
78fd4e5da5Sopenharmony_ci
79fd4e5da5Sopenharmony_ci  // Tests |function| with early return.
80fd4e5da5Sopenharmony_ci  function = spvtest::GetFunction(context->module(), 11);
81fd4e5da5Sopenharmony_ci  ASSERT_TRUE(function->HasEarlyReturn());
82fd4e5da5Sopenharmony_ci}
83fd4e5da5Sopenharmony_ci
84fd4e5da5Sopenharmony_ciTEST(FunctionTest, IsNotRecursive) {
85fd4e5da5Sopenharmony_ci  const std::string text = R"(
86fd4e5da5Sopenharmony_ciOpCapability Shader
87fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
88fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %1 "main"
89fd4e5da5Sopenharmony_ciOpExecutionMode %1 OriginUpperLeft
90fd4e5da5Sopenharmony_ciOpDecorate %2 DescriptorSet 439418829
91fd4e5da5Sopenharmony_ci%void = OpTypeVoid
92fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
93fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
94fd4e5da5Sopenharmony_ci%_struct_6 = OpTypeStruct %float %float
95fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %_struct_6
96fd4e5da5Sopenharmony_ci%1 = OpFunction %void Pure|Const %4
97fd4e5da5Sopenharmony_ci%8 = OpLabel
98fd4e5da5Sopenharmony_ci%2 = OpFunctionCall %_struct_6 %9
99fd4e5da5Sopenharmony_ciOpKill
100fd4e5da5Sopenharmony_ciOpFunctionEnd
101fd4e5da5Sopenharmony_ci%9 = OpFunction %_struct_6 None %7
102fd4e5da5Sopenharmony_ci%10 = OpLabel
103fd4e5da5Sopenharmony_ci%11 = OpFunctionCall %_struct_6 %12
104fd4e5da5Sopenharmony_ciOpUnreachable
105fd4e5da5Sopenharmony_ciOpFunctionEnd
106fd4e5da5Sopenharmony_ci%12 = OpFunction %_struct_6 None %7
107fd4e5da5Sopenharmony_ci%13 = OpLabel
108fd4e5da5Sopenharmony_ciOpUnreachable
109fd4e5da5Sopenharmony_ciOpFunctionEnd
110fd4e5da5Sopenharmony_ci)";
111fd4e5da5Sopenharmony_ci
112fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
113fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
114fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
115fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 9);
116fd4e5da5Sopenharmony_ci  EXPECT_FALSE(func->IsRecursive());
117fd4e5da5Sopenharmony_ci
118fd4e5da5Sopenharmony_ci  func = spvtest::GetFunction(ctx->module(), 12);
119fd4e5da5Sopenharmony_ci  EXPECT_FALSE(func->IsRecursive());
120fd4e5da5Sopenharmony_ci}
121fd4e5da5Sopenharmony_ci
122fd4e5da5Sopenharmony_ciTEST(FunctionTest, IsDirectlyRecursive) {
123fd4e5da5Sopenharmony_ci  const std::string text = R"(
124fd4e5da5Sopenharmony_ciOpCapability Shader
125fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
126fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %1 "main"
127fd4e5da5Sopenharmony_ciOpExecutionMode %1 OriginUpperLeft
128fd4e5da5Sopenharmony_ciOpDecorate %2 DescriptorSet 439418829
129fd4e5da5Sopenharmony_ci%void = OpTypeVoid
130fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
131fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
132fd4e5da5Sopenharmony_ci%_struct_6 = OpTypeStruct %float %float
133fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %_struct_6
134fd4e5da5Sopenharmony_ci%1 = OpFunction %void Pure|Const %4
135fd4e5da5Sopenharmony_ci%8 = OpLabel
136fd4e5da5Sopenharmony_ci%2 = OpFunctionCall %_struct_6 %9
137fd4e5da5Sopenharmony_ciOpKill
138fd4e5da5Sopenharmony_ciOpFunctionEnd
139fd4e5da5Sopenharmony_ci%9 = OpFunction %_struct_6 None %7
140fd4e5da5Sopenharmony_ci%10 = OpLabel
141fd4e5da5Sopenharmony_ci%11 = OpFunctionCall %_struct_6 %9
142fd4e5da5Sopenharmony_ciOpUnreachable
143fd4e5da5Sopenharmony_ciOpFunctionEnd
144fd4e5da5Sopenharmony_ci)";
145fd4e5da5Sopenharmony_ci
146fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
147fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
148fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
149fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 9);
150fd4e5da5Sopenharmony_ci  EXPECT_TRUE(func->IsRecursive());
151fd4e5da5Sopenharmony_ci}
152fd4e5da5Sopenharmony_ci
153fd4e5da5Sopenharmony_ciTEST(FunctionTest, IsIndirectlyRecursive) {
154fd4e5da5Sopenharmony_ci  const std::string text = R"(
155fd4e5da5Sopenharmony_ciOpCapability Shader
156fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
157fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %1 "main"
158fd4e5da5Sopenharmony_ciOpExecutionMode %1 OriginUpperLeft
159fd4e5da5Sopenharmony_ciOpDecorate %2 DescriptorSet 439418829
160fd4e5da5Sopenharmony_ci%void = OpTypeVoid
161fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
162fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
163fd4e5da5Sopenharmony_ci%_struct_6 = OpTypeStruct %float %float
164fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %_struct_6
165fd4e5da5Sopenharmony_ci%1 = OpFunction %void Pure|Const %4
166fd4e5da5Sopenharmony_ci%8 = OpLabel
167fd4e5da5Sopenharmony_ci%2 = OpFunctionCall %_struct_6 %9
168fd4e5da5Sopenharmony_ciOpKill
169fd4e5da5Sopenharmony_ciOpFunctionEnd
170fd4e5da5Sopenharmony_ci%9 = OpFunction %_struct_6 None %7
171fd4e5da5Sopenharmony_ci%10 = OpLabel
172fd4e5da5Sopenharmony_ci%11 = OpFunctionCall %_struct_6 %12
173fd4e5da5Sopenharmony_ciOpUnreachable
174fd4e5da5Sopenharmony_ciOpFunctionEnd
175fd4e5da5Sopenharmony_ci%12 = OpFunction %_struct_6 None %7
176fd4e5da5Sopenharmony_ci%13 = OpLabel
177fd4e5da5Sopenharmony_ci%14 = OpFunctionCall %_struct_6 %9
178fd4e5da5Sopenharmony_ciOpUnreachable
179fd4e5da5Sopenharmony_ciOpFunctionEnd
180fd4e5da5Sopenharmony_ci)";
181fd4e5da5Sopenharmony_ci
182fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
183fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
184fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
185fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 9);
186fd4e5da5Sopenharmony_ci  EXPECT_TRUE(func->IsRecursive());
187fd4e5da5Sopenharmony_ci
188fd4e5da5Sopenharmony_ci  func = spvtest::GetFunction(ctx->module(), 12);
189fd4e5da5Sopenharmony_ci  EXPECT_TRUE(func->IsRecursive());
190fd4e5da5Sopenharmony_ci}
191fd4e5da5Sopenharmony_ci
192fd4e5da5Sopenharmony_ciTEST(FunctionTest, IsNotRecuriseCallingRecursive) {
193fd4e5da5Sopenharmony_ci  const std::string text = R"(
194fd4e5da5Sopenharmony_ciOpCapability Shader
195fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
196fd4e5da5Sopenharmony_ciOpEntryPoint Fragment %1 "main"
197fd4e5da5Sopenharmony_ciOpExecutionMode %1 OriginUpperLeft
198fd4e5da5Sopenharmony_ciOpDecorate %2 DescriptorSet 439418829
199fd4e5da5Sopenharmony_ci%void = OpTypeVoid
200fd4e5da5Sopenharmony_ci%4 = OpTypeFunction %void
201fd4e5da5Sopenharmony_ci%float = OpTypeFloat 32
202fd4e5da5Sopenharmony_ci%_struct_6 = OpTypeStruct %float %float
203fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %_struct_6
204fd4e5da5Sopenharmony_ci%1 = OpFunction %void Pure|Const %4
205fd4e5da5Sopenharmony_ci%8 = OpLabel
206fd4e5da5Sopenharmony_ci%2 = OpFunctionCall %_struct_6 %9
207fd4e5da5Sopenharmony_ciOpKill
208fd4e5da5Sopenharmony_ciOpFunctionEnd
209fd4e5da5Sopenharmony_ci%9 = OpFunction %_struct_6 None %7
210fd4e5da5Sopenharmony_ci%10 = OpLabel
211fd4e5da5Sopenharmony_ci%11 = OpFunctionCall %_struct_6 %9
212fd4e5da5Sopenharmony_ciOpUnreachable
213fd4e5da5Sopenharmony_ciOpFunctionEnd
214fd4e5da5Sopenharmony_ci)";
215fd4e5da5Sopenharmony_ci
216fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
217fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
218fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
219fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 1);
220fd4e5da5Sopenharmony_ci  EXPECT_FALSE(func->IsRecursive());
221fd4e5da5Sopenharmony_ci}
222fd4e5da5Sopenharmony_ci
223fd4e5da5Sopenharmony_ciTEST(FunctionTest, NonSemanticInfoSkipIteration) {
224fd4e5da5Sopenharmony_ci  const std::string text = R"(
225fd4e5da5Sopenharmony_ciOpCapability Shader
226fd4e5da5Sopenharmony_ciOpCapability Linkage
227fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
228fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "NonSemantic.Test"
229fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
230fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
231fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
232fd4e5da5Sopenharmony_ci%4 = OpFunction %2 None %3
233fd4e5da5Sopenharmony_ci%5 = OpLabel
234fd4e5da5Sopenharmony_ci%6 = OpExtInst %2 %1 1
235fd4e5da5Sopenharmony_ciOpReturn
236fd4e5da5Sopenharmony_ciOpFunctionEnd
237fd4e5da5Sopenharmony_ci%7 = OpExtInst %2 %1 2
238fd4e5da5Sopenharmony_ci%8 = OpExtInst %2 %1 3
239fd4e5da5Sopenharmony_ci)";
240fd4e5da5Sopenharmony_ci
241fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
242fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
243fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
244fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 4);
245fd4e5da5Sopenharmony_ci  ASSERT_TRUE(func != nullptr);
246fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> non_semantic_ids;
247fd4e5da5Sopenharmony_ci  func->ForEachInst(
248fd4e5da5Sopenharmony_ci      [&non_semantic_ids](const Instruction* inst) {
249fd4e5da5Sopenharmony_ci        if (inst->opcode() == spv::Op::OpExtInst) {
250fd4e5da5Sopenharmony_ci          non_semantic_ids.insert(inst->result_id());
251fd4e5da5Sopenharmony_ci        }
252fd4e5da5Sopenharmony_ci      },
253fd4e5da5Sopenharmony_ci      true, false);
254fd4e5da5Sopenharmony_ci
255fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(6));
256fd4e5da5Sopenharmony_ci  EXPECT_EQ(0, non_semantic_ids.count(7));
257fd4e5da5Sopenharmony_ci  EXPECT_EQ(0, non_semantic_ids.count(8));
258fd4e5da5Sopenharmony_ci}
259fd4e5da5Sopenharmony_ci
260fd4e5da5Sopenharmony_ciTEST(FunctionTest, NonSemanticInfoIncludeIteration) {
261fd4e5da5Sopenharmony_ci  const std::string text = R"(
262fd4e5da5Sopenharmony_ciOpCapability Shader
263fd4e5da5Sopenharmony_ciOpCapability Linkage
264fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
265fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "NonSemantic.Test"
266fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
267fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
268fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
269fd4e5da5Sopenharmony_ci%4 = OpFunction %2 None %3
270fd4e5da5Sopenharmony_ci%5 = OpLabel
271fd4e5da5Sopenharmony_ci%6 = OpExtInst %2 %1 1
272fd4e5da5Sopenharmony_ciOpReturn
273fd4e5da5Sopenharmony_ciOpFunctionEnd
274fd4e5da5Sopenharmony_ci%7 = OpExtInst %2 %1 2
275fd4e5da5Sopenharmony_ci%8 = OpExtInst %2 %1 3
276fd4e5da5Sopenharmony_ci)";
277fd4e5da5Sopenharmony_ci
278fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
279fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
280fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
281fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 4);
282fd4e5da5Sopenharmony_ci  ASSERT_TRUE(func != nullptr);
283fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> non_semantic_ids;
284fd4e5da5Sopenharmony_ci  func->ForEachInst(
285fd4e5da5Sopenharmony_ci      [&non_semantic_ids](const Instruction* inst) {
286fd4e5da5Sopenharmony_ci        if (inst->opcode() == spv::Op::OpExtInst) {
287fd4e5da5Sopenharmony_ci          non_semantic_ids.insert(inst->result_id());
288fd4e5da5Sopenharmony_ci        }
289fd4e5da5Sopenharmony_ci      },
290fd4e5da5Sopenharmony_ci      true, true);
291fd4e5da5Sopenharmony_ci
292fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(6));
293fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(7));
294fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(8));
295fd4e5da5Sopenharmony_ci}
296fd4e5da5Sopenharmony_ci
297fd4e5da5Sopenharmony_ciTEST(FunctionTest, ReorderBlocksinStructuredOrder) {
298fd4e5da5Sopenharmony_ci  // The spir-v has the basic block in a random order.  We want to reorder them
299fd4e5da5Sopenharmony_ci  // in structured order.
300fd4e5da5Sopenharmony_ci  const std::string text = R"(
301fd4e5da5Sopenharmony_ci               OpCapability Shader
302fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
303fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %100 "PSMain"
304fd4e5da5Sopenharmony_ci               OpExecutionMode %PSMain OriginUpperLeft
305fd4e5da5Sopenharmony_ci               OpSource HLSL 600
306fd4e5da5Sopenharmony_ci        %int = OpTypeInt 32 1
307fd4e5da5Sopenharmony_ci       %void = OpTypeVoid
308fd4e5da5Sopenharmony_ci         %19 = OpTypeFunction %void
309fd4e5da5Sopenharmony_ci       %bool = OpTypeBool
310fd4e5da5Sopenharmony_ci%undef_bool = OpUndef %bool
311fd4e5da5Sopenharmony_ci%undef_int = OpUndef %int
312fd4e5da5Sopenharmony_ci        %100 = OpFunction %void None %19
313fd4e5da5Sopenharmony_ci          %11 = OpLabel
314fd4e5da5Sopenharmony_ci               OpSelectionMerge %10 None
315fd4e5da5Sopenharmony_ci               OpSwitch %undef_int %3 0 %2 10 %1
316fd4e5da5Sopenharmony_ci          %2 = OpLabel
317fd4e5da5Sopenharmony_ci               OpReturn
318fd4e5da5Sopenharmony_ci          %7 = OpLabel
319fd4e5da5Sopenharmony_ci               OpBranch %8
320fd4e5da5Sopenharmony_ci          %3 = OpLabel
321fd4e5da5Sopenharmony_ci               OpBranch %4
322fd4e5da5Sopenharmony_ci         %10 = OpLabel
323fd4e5da5Sopenharmony_ci               OpReturn
324fd4e5da5Sopenharmony_ci          %9 = OpLabel
325fd4e5da5Sopenharmony_ci               OpBranch %10
326fd4e5da5Sopenharmony_ci          %8 = OpLabel
327fd4e5da5Sopenharmony_ci               OpBranch %4
328fd4e5da5Sopenharmony_ci          %4 = OpLabel
329fd4e5da5Sopenharmony_ci               OpLoopMerge %9 %8 None
330fd4e5da5Sopenharmony_ci               OpBranchConditional %undef_bool %5 %9
331fd4e5da5Sopenharmony_ci          %1 = OpLabel
332fd4e5da5Sopenharmony_ci               OpReturn
333fd4e5da5Sopenharmony_ci          %6 = OpLabel
334fd4e5da5Sopenharmony_ci               OpBranch %7
335fd4e5da5Sopenharmony_ci          %5 = OpLabel
336fd4e5da5Sopenharmony_ci               OpSelectionMerge %7 None
337fd4e5da5Sopenharmony_ci               OpBranchConditional %undef_bool %6 %7
338fd4e5da5Sopenharmony_ci               OpFunctionEnd
339fd4e5da5Sopenharmony_ci)";
340fd4e5da5Sopenharmony_ci
341fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> ctx =
342fd4e5da5Sopenharmony_ci      spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
343fd4e5da5Sopenharmony_ci                            SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
344fd4e5da5Sopenharmony_ci  ASSERT_TRUE(ctx);
345fd4e5da5Sopenharmony_ci  auto* func = spvtest::GetFunction(ctx->module(), 100);
346fd4e5da5Sopenharmony_ci  ASSERT_TRUE(func);
347fd4e5da5Sopenharmony_ci  func->ReorderBasicBlocksInStructuredOrder();
348fd4e5da5Sopenharmony_ci
349fd4e5da5Sopenharmony_ci  auto first_block = func->begin();
350fd4e5da5Sopenharmony_ci  auto bb = first_block;
351fd4e5da5Sopenharmony_ci  for (++bb; bb != func->end(); ++bb) {
352fd4e5da5Sopenharmony_ci    EXPECT_EQ(bb->id(), (bb - first_block));
353fd4e5da5Sopenharmony_ci  }
354fd4e5da5Sopenharmony_ci}
355fd4e5da5Sopenharmony_ci
356fd4e5da5Sopenharmony_ci}  // namespace
357fd4e5da5Sopenharmony_ci}  // namespace opt
358fd4e5da5Sopenharmony_ci}  // namespace spvtools
359