1fd4e5da5Sopenharmony_ci// Copyright (c) 2016 Google Inc.
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 "source/opt/module.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include <memory>
18fd4e5da5Sopenharmony_ci#include <vector>
19fd4e5da5Sopenharmony_ci
20fd4e5da5Sopenharmony_ci#include "gmock/gmock.h"
21fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
22fd4e5da5Sopenharmony_ci#include "source/opt/build_module.h"
23fd4e5da5Sopenharmony_ci#include "spirv-tools/libspirv.hpp"
24fd4e5da5Sopenharmony_ci#include "test/opt/module_utils.h"
25fd4e5da5Sopenharmony_ci
26fd4e5da5Sopenharmony_cinamespace spvtools {
27fd4e5da5Sopenharmony_cinamespace opt {
28fd4e5da5Sopenharmony_cinamespace {
29fd4e5da5Sopenharmony_ci
30fd4e5da5Sopenharmony_ciusing ::testing::Eq;
31fd4e5da5Sopenharmony_ciusing spvtest::GetIdBound;
32fd4e5da5Sopenharmony_ci
33fd4e5da5Sopenharmony_ciTEST(ModuleTest, SetIdBound) {
34fd4e5da5Sopenharmony_ci  Module m;
35fd4e5da5Sopenharmony_ci  // It's initialized to 0.
36fd4e5da5Sopenharmony_ci  EXPECT_EQ(0u, GetIdBound(m));
37fd4e5da5Sopenharmony_ci
38fd4e5da5Sopenharmony_ci  m.SetIdBound(19);
39fd4e5da5Sopenharmony_ci  EXPECT_EQ(19u, GetIdBound(m));
40fd4e5da5Sopenharmony_ci
41fd4e5da5Sopenharmony_ci  m.SetIdBound(102);
42fd4e5da5Sopenharmony_ci  EXPECT_EQ(102u, GetIdBound(m));
43fd4e5da5Sopenharmony_ci}
44fd4e5da5Sopenharmony_ci
45fd4e5da5Sopenharmony_ci// Returns an IRContext owning the module formed by assembling the given text,
46fd4e5da5Sopenharmony_ci// then loading the result.
47fd4e5da5Sopenharmony_ciinline std::unique_ptr<IRContext> BuildModule(std::string text) {
48fd4e5da5Sopenharmony_ci  return spvtools::BuildModule(SPV_ENV_UNIVERSAL_1_1, nullptr, text,
49fd4e5da5Sopenharmony_ci                               SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
50fd4e5da5Sopenharmony_ci}
51fd4e5da5Sopenharmony_ci
52fd4e5da5Sopenharmony_ciTEST(ModuleTest, ComputeIdBound) {
53fd4e5da5Sopenharmony_ci  // Empty module case.
54fd4e5da5Sopenharmony_ci  EXPECT_EQ(1u, BuildModule("")->module()->ComputeIdBound());
55fd4e5da5Sopenharmony_ci  // Sensitive to result id
56fd4e5da5Sopenharmony_ci  EXPECT_EQ(2u, BuildModule("%void = OpTypeVoid")->module()->ComputeIdBound());
57fd4e5da5Sopenharmony_ci  // Sensitive to type id
58fd4e5da5Sopenharmony_ci  EXPECT_EQ(1000u,
59fd4e5da5Sopenharmony_ci            BuildModule("%a = OpTypeArray !999 3")->module()->ComputeIdBound());
60fd4e5da5Sopenharmony_ci  // Sensitive to a regular Id parameter
61fd4e5da5Sopenharmony_ci  EXPECT_EQ(2000u,
62fd4e5da5Sopenharmony_ci            BuildModule("OpDecorate !1999 0")->module()->ComputeIdBound());
63fd4e5da5Sopenharmony_ci  // Sensitive to a scope Id parameter.
64fd4e5da5Sopenharmony_ci  EXPECT_EQ(3000u,
65fd4e5da5Sopenharmony_ci            BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
66fd4e5da5Sopenharmony_ci                        "OpMemoryBarrier !2999 %b\n")
67fd4e5da5Sopenharmony_ci                ->module()
68fd4e5da5Sopenharmony_ci                ->ComputeIdBound());
69fd4e5da5Sopenharmony_ci  // Sensitive to a semantics Id parameter
70fd4e5da5Sopenharmony_ci  EXPECT_EQ(4000u,
71fd4e5da5Sopenharmony_ci            BuildModule("%f = OpFunction %void None %fntype %a = OpLabel "
72fd4e5da5Sopenharmony_ci                        "OpMemoryBarrier %b !3999\n")
73fd4e5da5Sopenharmony_ci                ->module()
74fd4e5da5Sopenharmony_ci                ->ComputeIdBound());
75fd4e5da5Sopenharmony_ci}
76fd4e5da5Sopenharmony_ci
77fd4e5da5Sopenharmony_ciTEST(ModuleTest, OstreamOperator) {
78fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
79fd4e5da5Sopenharmony_ciOpCapability Linkage
80fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
81fd4e5da5Sopenharmony_ciOpName %7 "restrict"
82fd4e5da5Sopenharmony_ciOpDecorate %8 Restrict
83fd4e5da5Sopenharmony_ci%9 = OpTypeVoid
84fd4e5da5Sopenharmony_ci%10 = OpTypeInt 32 0
85fd4e5da5Sopenharmony_ci%11 = OpTypeStruct %10 %10
86fd4e5da5Sopenharmony_ci%12 = OpTypePointer Function %10
87fd4e5da5Sopenharmony_ci%13 = OpTypePointer Function %11
88fd4e5da5Sopenharmony_ci%14 = OpConstant %10 0
89fd4e5da5Sopenharmony_ci%15 = OpConstant %10 1
90fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %9
91fd4e5da5Sopenharmony_ci%1 = OpFunction %9 None %7
92fd4e5da5Sopenharmony_ci%2 = OpLabel
93fd4e5da5Sopenharmony_ci%8 = OpVariable %13 Function
94fd4e5da5Sopenharmony_ci%3 = OpAccessChain %12 %8 %14
95fd4e5da5Sopenharmony_ci%4 = OpLoad %10 %3
96fd4e5da5Sopenharmony_ci%5 = OpAccessChain %12 %8 %15
97fd4e5da5Sopenharmony_ci%6 = OpLoad %10 %5
98fd4e5da5Sopenharmony_ciOpReturn
99fd4e5da5Sopenharmony_ciOpFunctionEnd)";
100fd4e5da5Sopenharmony_ci
101fd4e5da5Sopenharmony_ci  std::string s;
102fd4e5da5Sopenharmony_ci  std::ostringstream str(s);
103fd4e5da5Sopenharmony_ci  str << *BuildModule(text)->module();
104fd4e5da5Sopenharmony_ci  EXPECT_EQ(text, str.str());
105fd4e5da5Sopenharmony_ci}
106fd4e5da5Sopenharmony_ci
107fd4e5da5Sopenharmony_ciTEST(ModuleTest, OstreamOperatorInt64) {
108fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
109fd4e5da5Sopenharmony_ciOpCapability Linkage
110fd4e5da5Sopenharmony_ciOpCapability Int64
111fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
112fd4e5da5Sopenharmony_ciOpName %7 "restrict"
113fd4e5da5Sopenharmony_ciOpDecorate %5 Restrict
114fd4e5da5Sopenharmony_ci%9 = OpTypeVoid
115fd4e5da5Sopenharmony_ci%10 = OpTypeInt 64 0
116fd4e5da5Sopenharmony_ci%11 = OpTypeStruct %10 %10
117fd4e5da5Sopenharmony_ci%12 = OpTypePointer Function %10
118fd4e5da5Sopenharmony_ci%13 = OpTypePointer Function %11
119fd4e5da5Sopenharmony_ci%14 = OpConstant %10 0
120fd4e5da5Sopenharmony_ci%15 = OpConstant %10 1
121fd4e5da5Sopenharmony_ci%16 = OpConstant %10 4294967297
122fd4e5da5Sopenharmony_ci%7 = OpTypeFunction %9
123fd4e5da5Sopenharmony_ci%1 = OpFunction %9 None %7
124fd4e5da5Sopenharmony_ci%2 = OpLabel
125fd4e5da5Sopenharmony_ci%5 = OpVariable %12 Function
126fd4e5da5Sopenharmony_ci%6 = OpLoad %10 %5
127fd4e5da5Sopenharmony_ciOpSelectionMerge %3 None
128fd4e5da5Sopenharmony_ciOpSwitch %6 %3 4294967297 %4
129fd4e5da5Sopenharmony_ci%4 = OpLabel
130fd4e5da5Sopenharmony_ciOpBranch %3
131fd4e5da5Sopenharmony_ci%3 = OpLabel
132fd4e5da5Sopenharmony_ciOpReturn
133fd4e5da5Sopenharmony_ciOpFunctionEnd)";
134fd4e5da5Sopenharmony_ci
135fd4e5da5Sopenharmony_ci  std::string s;
136fd4e5da5Sopenharmony_ci  std::ostringstream str(s);
137fd4e5da5Sopenharmony_ci  str << *BuildModule(text)->module();
138fd4e5da5Sopenharmony_ci  EXPECT_EQ(text, str.str());
139fd4e5da5Sopenharmony_ci}
140fd4e5da5Sopenharmony_ci
141fd4e5da5Sopenharmony_ciTEST(ModuleTest, IdBoundTestAtLimit) {
142fd4e5da5Sopenharmony_ci  const std::string text = R"(
143fd4e5da5Sopenharmony_ciOpCapability Shader
144fd4e5da5Sopenharmony_ciOpCapability Linkage
145fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
146fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
147fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
148fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
149fd4e5da5Sopenharmony_ci%4 = OpLabel
150fd4e5da5Sopenharmony_ciOpReturn
151fd4e5da5Sopenharmony_ciOpFunctionEnd)";
152fd4e5da5Sopenharmony_ci
153fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> context = BuildModule(text);
154fd4e5da5Sopenharmony_ci  uint32_t current_bound = context->module()->id_bound();
155fd4e5da5Sopenharmony_ci  context->set_max_id_bound(current_bound);
156fd4e5da5Sopenharmony_ci  uint32_t next_id_bound = context->module()->TakeNextIdBound();
157fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, 0);
158fd4e5da5Sopenharmony_ci  EXPECT_EQ(current_bound, context->module()->id_bound());
159fd4e5da5Sopenharmony_ci  next_id_bound = context->module()->TakeNextIdBound();
160fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, 0);
161fd4e5da5Sopenharmony_ci}
162fd4e5da5Sopenharmony_ci
163fd4e5da5Sopenharmony_ciTEST(ModuleTest, IdBoundTestBelowLimit) {
164fd4e5da5Sopenharmony_ci  const std::string text = R"(
165fd4e5da5Sopenharmony_ciOpCapability Shader
166fd4e5da5Sopenharmony_ciOpCapability Linkage
167fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
168fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
169fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
170fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
171fd4e5da5Sopenharmony_ci%4 = OpLabel
172fd4e5da5Sopenharmony_ciOpReturn
173fd4e5da5Sopenharmony_ciOpFunctionEnd)";
174fd4e5da5Sopenharmony_ci
175fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> context = BuildModule(text);
176fd4e5da5Sopenharmony_ci  uint32_t current_bound = context->module()->id_bound();
177fd4e5da5Sopenharmony_ci  context->set_max_id_bound(current_bound + 100);
178fd4e5da5Sopenharmony_ci  uint32_t next_id_bound = context->module()->TakeNextIdBound();
179fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, current_bound);
180fd4e5da5Sopenharmony_ci  EXPECT_EQ(current_bound + 1, context->module()->id_bound());
181fd4e5da5Sopenharmony_ci  next_id_bound = context->module()->TakeNextIdBound();
182fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, current_bound + 1);
183fd4e5da5Sopenharmony_ci}
184fd4e5da5Sopenharmony_ci
185fd4e5da5Sopenharmony_ciTEST(ModuleTest, IdBoundTestNearLimit) {
186fd4e5da5Sopenharmony_ci  const std::string text = R"(
187fd4e5da5Sopenharmony_ciOpCapability Shader
188fd4e5da5Sopenharmony_ciOpCapability Linkage
189fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
190fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
191fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
192fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
193fd4e5da5Sopenharmony_ci%4 = OpLabel
194fd4e5da5Sopenharmony_ciOpReturn
195fd4e5da5Sopenharmony_ciOpFunctionEnd)";
196fd4e5da5Sopenharmony_ci
197fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> context = BuildModule(text);
198fd4e5da5Sopenharmony_ci  uint32_t current_bound = context->module()->id_bound();
199fd4e5da5Sopenharmony_ci  context->set_max_id_bound(current_bound + 1);
200fd4e5da5Sopenharmony_ci  uint32_t next_id_bound = context->module()->TakeNextIdBound();
201fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, current_bound);
202fd4e5da5Sopenharmony_ci  EXPECT_EQ(current_bound + 1, context->module()->id_bound());
203fd4e5da5Sopenharmony_ci  next_id_bound = context->module()->TakeNextIdBound();
204fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, 0);
205fd4e5da5Sopenharmony_ci}
206fd4e5da5Sopenharmony_ci
207fd4e5da5Sopenharmony_ciTEST(ModuleTest, IdBoundTestUIntMax) {
208fd4e5da5Sopenharmony_ci  const std::string text = R"(
209fd4e5da5Sopenharmony_ciOpCapability Shader
210fd4e5da5Sopenharmony_ciOpCapability Linkage
211fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
212fd4e5da5Sopenharmony_ci%1 = OpTypeVoid
213fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %1
214fd4e5da5Sopenharmony_ci%3 = OpFunction %1 None %2
215fd4e5da5Sopenharmony_ci%4294967294 = OpLabel ; ID is UINT_MAX-1
216fd4e5da5Sopenharmony_ciOpReturn
217fd4e5da5Sopenharmony_ciOpFunctionEnd)";
218fd4e5da5Sopenharmony_ci
219fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> context = BuildModule(text);
220fd4e5da5Sopenharmony_ci  uint32_t current_bound = context->module()->id_bound();
221fd4e5da5Sopenharmony_ci
222fd4e5da5Sopenharmony_ci  // Expecting |BuildModule| to preserve the numeric ids.
223fd4e5da5Sopenharmony_ci  EXPECT_EQ(current_bound, std::numeric_limits<uint32_t>::max());
224fd4e5da5Sopenharmony_ci
225fd4e5da5Sopenharmony_ci  context->set_max_id_bound(current_bound);
226fd4e5da5Sopenharmony_ci  uint32_t next_id_bound = context->module()->TakeNextIdBound();
227fd4e5da5Sopenharmony_ci  EXPECT_EQ(next_id_bound, 0);
228fd4e5da5Sopenharmony_ci  EXPECT_EQ(current_bound, context->module()->id_bound());
229fd4e5da5Sopenharmony_ci}
230fd4e5da5Sopenharmony_ci
231fd4e5da5Sopenharmony_ci// Tests that "text" does not change when it is assembled, converted into a
232fd4e5da5Sopenharmony_ci// module, converted back to a binary, and then disassembled.
233fd4e5da5Sopenharmony_civoid AssembleAndDisassemble(const std::string& text) {
234fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> context = BuildModule(text);
235fd4e5da5Sopenharmony_ci  std::vector<uint32_t> binary;
236fd4e5da5Sopenharmony_ci
237fd4e5da5Sopenharmony_ci  context->module()->ToBinary(&binary, false);
238fd4e5da5Sopenharmony_ci
239fd4e5da5Sopenharmony_ci  SpirvTools tools(SPV_ENV_UNIVERSAL_1_1);
240fd4e5da5Sopenharmony_ci  std::string s;
241fd4e5da5Sopenharmony_ci  tools.Disassemble(binary, &s);
242fd4e5da5Sopenharmony_ci  EXPECT_EQ(s, text);
243fd4e5da5Sopenharmony_ci}
244fd4e5da5Sopenharmony_ci
245fd4e5da5Sopenharmony_ciTEST(ModuleTest, TrailingOpLine) {
246fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
247fd4e5da5Sopenharmony_ciOpCapability Linkage
248fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
249fd4e5da5Sopenharmony_ci%5 = OpString "file.ext"
250fd4e5da5Sopenharmony_ci%void = OpTypeVoid
251fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
252fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %2
253fd4e5da5Sopenharmony_ci%4 = OpLabel
254fd4e5da5Sopenharmony_ciOpReturn
255fd4e5da5Sopenharmony_ciOpFunctionEnd
256fd4e5da5Sopenharmony_ciOpLine %5 1 0
257fd4e5da5Sopenharmony_ci)";
258fd4e5da5Sopenharmony_ci
259fd4e5da5Sopenharmony_ci  AssembleAndDisassemble(text);
260fd4e5da5Sopenharmony_ci}
261fd4e5da5Sopenharmony_ci
262fd4e5da5Sopenharmony_ciTEST(ModuleTest, TrailingOpNoLine) {
263fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
264fd4e5da5Sopenharmony_ciOpCapability Linkage
265fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
266fd4e5da5Sopenharmony_ci%void = OpTypeVoid
267fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
268fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %2
269fd4e5da5Sopenharmony_ci%4 = OpLabel
270fd4e5da5Sopenharmony_ciOpReturn
271fd4e5da5Sopenharmony_ciOpFunctionEnd
272fd4e5da5Sopenharmony_ciOpNoLine
273fd4e5da5Sopenharmony_ci)";
274fd4e5da5Sopenharmony_ci
275fd4e5da5Sopenharmony_ci  AssembleAndDisassemble(text);
276fd4e5da5Sopenharmony_ci}
277fd4e5da5Sopenharmony_ci
278fd4e5da5Sopenharmony_ciTEST(ModuleTest, MulitpleTrailingOpLine) {
279fd4e5da5Sopenharmony_ci  const std::string text = R"(OpCapability Shader
280fd4e5da5Sopenharmony_ciOpCapability Linkage
281fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
282fd4e5da5Sopenharmony_ci%5 = OpString "file.ext"
283fd4e5da5Sopenharmony_ci%void = OpTypeVoid
284fd4e5da5Sopenharmony_ci%2 = OpTypeFunction %void
285fd4e5da5Sopenharmony_ci%3 = OpFunction %void None %2
286fd4e5da5Sopenharmony_ci%4 = OpLabel
287fd4e5da5Sopenharmony_ciOpReturn
288fd4e5da5Sopenharmony_ciOpFunctionEnd
289fd4e5da5Sopenharmony_ciOpLine %5 1 0
290fd4e5da5Sopenharmony_ciOpNoLine
291fd4e5da5Sopenharmony_ciOpLine %5 1 1
292fd4e5da5Sopenharmony_ci)";
293fd4e5da5Sopenharmony_ci
294fd4e5da5Sopenharmony_ci  AssembleAndDisassemble(text);
295fd4e5da5Sopenharmony_ci}
296fd4e5da5Sopenharmony_ci
297fd4e5da5Sopenharmony_ciTEST(ModuleTest, NonSemanticInfoIteration) {
298fd4e5da5Sopenharmony_ci  const std::string text = R"(
299fd4e5da5Sopenharmony_ciOpCapability Shader
300fd4e5da5Sopenharmony_ciOpCapability Linkage
301fd4e5da5Sopenharmony_ciOpExtension "SPV_KHR_non_semantic_info"
302fd4e5da5Sopenharmony_ci%1 = OpExtInstImport "NonSemantic.Test"
303fd4e5da5Sopenharmony_ciOpMemoryModel Logical GLSL450
304fd4e5da5Sopenharmony_ci%2 = OpTypeVoid
305fd4e5da5Sopenharmony_ci%3 = OpTypeFunction %2
306fd4e5da5Sopenharmony_ci%4 = OpExtInst %2 %1 1
307fd4e5da5Sopenharmony_ci%5 = OpFunction %2 None %3
308fd4e5da5Sopenharmony_ci%6 = OpLabel
309fd4e5da5Sopenharmony_ci%7 = OpExtInst %2 %1 1
310fd4e5da5Sopenharmony_ciOpReturn
311fd4e5da5Sopenharmony_ciOpFunctionEnd
312fd4e5da5Sopenharmony_ci%8 = OpExtInst %2 %1 1
313fd4e5da5Sopenharmony_ci%9 = OpFunction %2 None %3
314fd4e5da5Sopenharmony_ci%10 = OpLabel
315fd4e5da5Sopenharmony_ci%11 = OpExtInst %2 %1 1
316fd4e5da5Sopenharmony_ciOpReturn
317fd4e5da5Sopenharmony_ciOpFunctionEnd
318fd4e5da5Sopenharmony_ci%12 = OpExtInst %2 %1 1
319fd4e5da5Sopenharmony_ci)";
320fd4e5da5Sopenharmony_ci
321fd4e5da5Sopenharmony_ci  std::unique_ptr<IRContext> context = BuildModule(text);
322fd4e5da5Sopenharmony_ci  std::unordered_set<uint32_t> non_semantic_ids;
323fd4e5da5Sopenharmony_ci  context->module()->ForEachInst(
324fd4e5da5Sopenharmony_ci      [&non_semantic_ids](const Instruction* inst) {
325fd4e5da5Sopenharmony_ci        if (inst->opcode() == spv::Op::OpExtInst) {
326fd4e5da5Sopenharmony_ci          non_semantic_ids.insert(inst->result_id());
327fd4e5da5Sopenharmony_ci        }
328fd4e5da5Sopenharmony_ci      },
329fd4e5da5Sopenharmony_ci      false);
330fd4e5da5Sopenharmony_ci
331fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(4));
332fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(7));
333fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(8));
334fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(11));
335fd4e5da5Sopenharmony_ci  EXPECT_EQ(1, non_semantic_ids.count(12));
336fd4e5da5Sopenharmony_ci}
337fd4e5da5Sopenharmony_ci}  // namespace
338fd4e5da5Sopenharmony_ci}  // namespace opt
339fd4e5da5Sopenharmony_ci}  // namespace spvtools
340