1fd4e5da5Sopenharmony_ci// Copyright (c) 2021 Alastair F. Donaldson
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/fuzz/available_instructions.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include "gtest/gtest.h"
18fd4e5da5Sopenharmony_ci#include "source/fuzz/fuzzer_util.h"
19fd4e5da5Sopenharmony_ci#include "test/fuzz/fuzz_test_util.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace fuzz {
23fd4e5da5Sopenharmony_cinamespace {
24fd4e5da5Sopenharmony_ci
25fd4e5da5Sopenharmony_ciTEST(AvailableInstructionsTest, BasicTest) {
26fd4e5da5Sopenharmony_ci  std::string shader = R"(
27fd4e5da5Sopenharmony_ci               OpCapability Shader
28fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
29fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
30fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
31fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
32fd4e5da5Sopenharmony_ci               OpSource ESSL 320
33fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
34fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
35fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
36fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
37fd4e5da5Sopenharmony_ci          %8 = OpTypeFloat 32
38fd4e5da5Sopenharmony_ci          %9 = OpTypePointer Function %8
39fd4e5da5Sopenharmony_ci         %10 = OpTypeFunction %6 %7 %9
40fd4e5da5Sopenharmony_ci         %15 = OpTypeVector %8 2
41fd4e5da5Sopenharmony_ci         %16 = OpTypePointer Private %15
42fd4e5da5Sopenharmony_ci         %17 = OpVariable %16 Private
43fd4e5da5Sopenharmony_ci         %18 = OpConstant %8 1
44fd4e5da5Sopenharmony_ci         %19 = OpConstant %8 2
45fd4e5da5Sopenharmony_ci         %20 = OpConstantComposite %15 %18 %19
46fd4e5da5Sopenharmony_ci         %21 = OpTypeVector %8 4
47fd4e5da5Sopenharmony_ci         %22 = OpTypePointer Private %21
48fd4e5da5Sopenharmony_ci         %23 = OpVariable %22 Private
49fd4e5da5Sopenharmony_ci         %24 = OpConstant %8 10
50fd4e5da5Sopenharmony_ci         %25 = OpConstant %8 20
51fd4e5da5Sopenharmony_ci         %26 = OpConstant %8 30
52fd4e5da5Sopenharmony_ci         %27 = OpConstant %8 40
53fd4e5da5Sopenharmony_ci         %28 = OpConstantComposite %21 %24 %25 %26 %27
54fd4e5da5Sopenharmony_ci         %31 = OpTypeInt 32 0
55fd4e5da5Sopenharmony_ci         %32 = OpConstant %31 0
56fd4e5da5Sopenharmony_ci         %33 = OpTypePointer Private %8
57fd4e5da5Sopenharmony_ci         %41 = OpTypeBool
58fd4e5da5Sopenharmony_ci         %46 = OpConstant %6 1
59fd4e5da5Sopenharmony_ci         %54 = OpConstant %6 10
60fd4e5da5Sopenharmony_ci         %57 = OpConstant %31 3
61fd4e5da5Sopenharmony_ci         %61 = OpConstant %6 0
62fd4e5da5Sopenharmony_ci         %66 = OpConstant %6 3
63fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
64fd4e5da5Sopenharmony_ci          %5 = OpLabel
65fd4e5da5Sopenharmony_ci         %55 = OpVariable %7 Function
66fd4e5da5Sopenharmony_ci         %56 = OpVariable %9 Function
67fd4e5da5Sopenharmony_ci         %65 = OpVariable %7 Function
68fd4e5da5Sopenharmony_ci         %68 = OpVariable %7 Function
69fd4e5da5Sopenharmony_ci               OpStore %17 %20
70fd4e5da5Sopenharmony_ci               OpStore %23 %28
71fd4e5da5Sopenharmony_ci               OpStore %55 %54
72fd4e5da5Sopenharmony_ci         %58 = OpAccessChain %33 %23 %57
73fd4e5da5Sopenharmony_ci         %59 = OpLoad %8 %58
74fd4e5da5Sopenharmony_ci               OpStore %56 %59
75fd4e5da5Sopenharmony_ci         %60 = OpFunctionCall %6 %13 %55 %56
76fd4e5da5Sopenharmony_ci        %100 = OpCopyObject %21 %28
77fd4e5da5Sopenharmony_ci         %62 = OpSGreaterThan %41 %60 %61
78fd4e5da5Sopenharmony_ci               OpSelectionMerge %64 None
79fd4e5da5Sopenharmony_ci               OpBranchConditional %62 %63 %67
80fd4e5da5Sopenharmony_ci         %63 = OpLabel
81fd4e5da5Sopenharmony_ci               OpStore %65 %66
82fd4e5da5Sopenharmony_ci        %101 = OpCopyObject %21 %28
83fd4e5da5Sopenharmony_ci               OpBranch %64
84fd4e5da5Sopenharmony_ci         %67 = OpLabel
85fd4e5da5Sopenharmony_ci               OpStore %68 %61
86fd4e5da5Sopenharmony_ci               OpBranch %69
87fd4e5da5Sopenharmony_ci         %69 = OpLabel
88fd4e5da5Sopenharmony_ci               OpLoopMerge %71 %72 None
89fd4e5da5Sopenharmony_ci               OpBranch %73
90fd4e5da5Sopenharmony_ci         %73 = OpLabel
91fd4e5da5Sopenharmony_ci         %74 = OpLoad %6 %68
92fd4e5da5Sopenharmony_ci         %75 = OpSLessThan %41 %74 %54
93fd4e5da5Sopenharmony_ci               OpBranchConditional %75 %70 %71
94fd4e5da5Sopenharmony_ci         %70 = OpLabel
95fd4e5da5Sopenharmony_ci         %76 = OpLoad %6 %65
96fd4e5da5Sopenharmony_ci         %77 = OpIAdd %6 %76 %46
97fd4e5da5Sopenharmony_ci               OpStore %65 %77
98fd4e5da5Sopenharmony_ci               OpBranch %72
99fd4e5da5Sopenharmony_ci         %72 = OpLabel
100fd4e5da5Sopenharmony_ci         %78 = OpLoad %6 %68
101fd4e5da5Sopenharmony_ci         %79 = OpIAdd %6 %78 %46
102fd4e5da5Sopenharmony_ci               OpStore %68 %79
103fd4e5da5Sopenharmony_ci               OpBranch %69
104fd4e5da5Sopenharmony_ci         %71 = OpLabel
105fd4e5da5Sopenharmony_ci        %102 = OpCopyObject %21 %28
106fd4e5da5Sopenharmony_ci               OpBranch %64
107fd4e5da5Sopenharmony_ci         %64 = OpLabel
108fd4e5da5Sopenharmony_ci               OpReturn
109fd4e5da5Sopenharmony_ci               OpFunctionEnd
110fd4e5da5Sopenharmony_ci         %13 = OpFunction %6 None %10
111fd4e5da5Sopenharmony_ci         %11 = OpFunctionParameter %7
112fd4e5da5Sopenharmony_ci         %12 = OpFunctionParameter %9
113fd4e5da5Sopenharmony_ci         %14 = OpLabel
114fd4e5da5Sopenharmony_ci         %29 = OpVariable %7 Function
115fd4e5da5Sopenharmony_ci         %30 = OpLoad %6 %11
116fd4e5da5Sopenharmony_ci         %34 = OpAccessChain %33 %17 %32
117fd4e5da5Sopenharmony_ci         %35 = OpLoad %8 %34
118fd4e5da5Sopenharmony_ci         %36 = OpConvertFToS %6 %35
119fd4e5da5Sopenharmony_ci         %37 = OpIAdd %6 %30 %36
120fd4e5da5Sopenharmony_ci               OpStore %29 %37
121fd4e5da5Sopenharmony_ci         %38 = OpLoad %6 %11
122fd4e5da5Sopenharmony_ci         %39 = OpLoad %8 %12
123fd4e5da5Sopenharmony_ci         %40 = OpConvertFToS %6 %39
124fd4e5da5Sopenharmony_ci         %42 = OpSLessThan %41 %38 %40
125fd4e5da5Sopenharmony_ci        %103 = OpCopyObject %21 %28
126fd4e5da5Sopenharmony_ci               OpSelectionMerge %44 None
127fd4e5da5Sopenharmony_ci               OpBranchConditional %42 %43 %48
128fd4e5da5Sopenharmony_ci         %43 = OpLabel
129fd4e5da5Sopenharmony_ci         %45 = OpLoad %6 %29
130fd4e5da5Sopenharmony_ci         %47 = OpIAdd %6 %45 %46
131fd4e5da5Sopenharmony_ci               OpStore %29 %47
132fd4e5da5Sopenharmony_ci               OpBranch %44
133fd4e5da5Sopenharmony_ci         %48 = OpLabel
134fd4e5da5Sopenharmony_ci         %49 = OpLoad %6 %29
135fd4e5da5Sopenharmony_ci         %50 = OpISub %6 %49 %46
136fd4e5da5Sopenharmony_ci               OpStore %29 %50
137fd4e5da5Sopenharmony_ci               OpBranch %44
138fd4e5da5Sopenharmony_ci         %44 = OpLabel
139fd4e5da5Sopenharmony_ci         %51 = OpLoad %6 %29
140fd4e5da5Sopenharmony_ci               OpReturnValue %51
141fd4e5da5Sopenharmony_ci               OpFunctionEnd
142fd4e5da5Sopenharmony_ci  )";
143fd4e5da5Sopenharmony_ci
144fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
145fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
146fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
147fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
148fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
149fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
150fd4e5da5Sopenharmony_ci
151fd4e5da5Sopenharmony_ci  opt::Instruction* i1 = context->get_def_use_mgr()->GetDef(55);
152fd4e5da5Sopenharmony_ci  opt::Instruction* i2 = context->get_def_use_mgr()->GetDef(101);
153fd4e5da5Sopenharmony_ci  opt::Instruction* i3 = &*context->cfg()->block(67)->begin();
154fd4e5da5Sopenharmony_ci  opt::Instruction* i4 = context->get_def_use_mgr()->GetDef(74);
155fd4e5da5Sopenharmony_ci  opt::Instruction* i5 = context->get_def_use_mgr()->GetDef(102);
156fd4e5da5Sopenharmony_ci  opt::Instruction* i6 = context->get_def_use_mgr()->GetDef(30);
157fd4e5da5Sopenharmony_ci  opt::Instruction* i7 = context->get_def_use_mgr()->GetDef(47);
158fd4e5da5Sopenharmony_ci  opt::Instruction* i8 = context->get_def_use_mgr()->GetDef(50);
159fd4e5da5Sopenharmony_ci  opt::Instruction* i9 = context->get_def_use_mgr()->GetDef(51);
160fd4e5da5Sopenharmony_ci
161fd4e5da5Sopenharmony_ci  {
162fd4e5da5Sopenharmony_ci    AvailableInstructions no_instructions(
163fd4e5da5Sopenharmony_ci        context.get(),
164fd4e5da5Sopenharmony_ci        [](opt::IRContext*, opt::Instruction*) -> bool { return false; });
165fd4e5da5Sopenharmony_ci    for (auto i : {i1, i2, i3, i4, i5, i6, i7, i8, i9}) {
166fd4e5da5Sopenharmony_ci      auto available = no_instructions.GetAvailableBeforeInstruction(i);
167fd4e5da5Sopenharmony_ci      ASSERT_EQ(0, available.size());
168fd4e5da5Sopenharmony_ci      ASSERT_TRUE(available.empty());
169fd4e5da5Sopenharmony_ci    }
170fd4e5da5Sopenharmony_ci  }
171fd4e5da5Sopenharmony_ci  {
172fd4e5da5Sopenharmony_ci    AvailableInstructions all_instructions(
173fd4e5da5Sopenharmony_ci        context.get(),
174fd4e5da5Sopenharmony_ci        [](opt::IRContext*, opt::Instruction*) -> bool { return true; });
175fd4e5da5Sopenharmony_ci    {
176fd4e5da5Sopenharmony_ci      auto available = all_instructions.GetAvailableBeforeInstruction(i1);
177fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
178fd4e5da5Sopenharmony_ci      ASSERT_EQ(30, available.size());
179fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
180fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
181fd4e5da5Sopenharmony_ci    }
182fd4e5da5Sopenharmony_ci    {
183fd4e5da5Sopenharmony_ci      auto available = all_instructions.GetAvailableBeforeInstruction(i2);
184fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
185fd4e5da5Sopenharmony_ci      ASSERT_EQ(46, available.size());
186fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
187fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypePointer, available[3]->opcode());
188fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
189fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpFunctionCall, available[40]->opcode());
190fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpStore, available[45]->opcode());
191fd4e5da5Sopenharmony_ci    }
192fd4e5da5Sopenharmony_ci    {
193fd4e5da5Sopenharmony_ci      auto available = all_instructions.GetAvailableBeforeInstruction(i3);
194fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
195fd4e5da5Sopenharmony_ci      ASSERT_EQ(45, available.size());
196fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
197fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypePointer, available[3]->opcode());
198fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpVariable, available[15]->opcode());
199fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpFunctionCall, available[40]->opcode());
200fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpBranchConditional, available[44]->opcode());
201fd4e5da5Sopenharmony_ci    }
202fd4e5da5Sopenharmony_ci    {
203fd4e5da5Sopenharmony_ci      auto available = all_instructions.GetAvailableBeforeInstruction(i6);
204fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
205fd4e5da5Sopenharmony_ci      ASSERT_EQ(33, available.size());
206fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypeVoid, available[0]->opcode());
207fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypeFloat, available[4]->opcode());
208fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpTypePointer, available[8]->opcode());
209fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[12]->opcode());
210fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstant, available[16]->opcode());
211fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpFunctionParameter, available[30]->opcode());
212fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpFunctionParameter, available[31]->opcode());
213fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpVariable, available[32]->opcode());
214fd4e5da5Sopenharmony_ci    }
215fd4e5da5Sopenharmony_ci  }
216fd4e5da5Sopenharmony_ci  {
217fd4e5da5Sopenharmony_ci    AvailableInstructions vector_instructions(
218fd4e5da5Sopenharmony_ci        context.get(),
219fd4e5da5Sopenharmony_ci        [](opt::IRContext* ir_context, opt::Instruction* inst) -> bool {
220fd4e5da5Sopenharmony_ci          return inst->type_id() != 0 && ir_context->get_type_mgr()
221fd4e5da5Sopenharmony_ci                                                 ->GetType(inst->type_id())
222fd4e5da5Sopenharmony_ci                                                 ->AsVector() != nullptr;
223fd4e5da5Sopenharmony_ci        });
224fd4e5da5Sopenharmony_ci    {
225fd4e5da5Sopenharmony_ci      auto available = vector_instructions.GetAvailableBeforeInstruction(i4);
226fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
227fd4e5da5Sopenharmony_ci      ASSERT_EQ(3, available.size());
228fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
229fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
230fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpCopyObject, available[2]->opcode());
231fd4e5da5Sopenharmony_ci    }
232fd4e5da5Sopenharmony_ci    {
233fd4e5da5Sopenharmony_ci      auto available = vector_instructions.GetAvailableBeforeInstruction(i5);
234fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
235fd4e5da5Sopenharmony_ci      ASSERT_EQ(3, available.size());
236fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
237fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
238fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpCopyObject, available[2]->opcode());
239fd4e5da5Sopenharmony_ci    }
240fd4e5da5Sopenharmony_ci    {
241fd4e5da5Sopenharmony_ci      auto available = vector_instructions.GetAvailableBeforeInstruction(i6);
242fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
243fd4e5da5Sopenharmony_ci      ASSERT_EQ(2, available.size());
244fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[0]->opcode());
245fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpConstantComposite, available[1]->opcode());
246fd4e5da5Sopenharmony_ci    }
247fd4e5da5Sopenharmony_ci  }
248fd4e5da5Sopenharmony_ci  {
249fd4e5da5Sopenharmony_ci    AvailableInstructions integer_add_instructions(
250fd4e5da5Sopenharmony_ci        context.get(), [](opt::IRContext*, opt::Instruction* inst) -> bool {
251fd4e5da5Sopenharmony_ci          return inst->opcode() == spv::Op::OpIAdd;
252fd4e5da5Sopenharmony_ci        });
253fd4e5da5Sopenharmony_ci    {
254fd4e5da5Sopenharmony_ci      auto available =
255fd4e5da5Sopenharmony_ci          integer_add_instructions.GetAvailableBeforeInstruction(i7);
256fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
257fd4e5da5Sopenharmony_ci      ASSERT_EQ(1, available.size());
258fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
259fd4e5da5Sopenharmony_ci    }
260fd4e5da5Sopenharmony_ci    {
261fd4e5da5Sopenharmony_ci      auto available =
262fd4e5da5Sopenharmony_ci          integer_add_instructions.GetAvailableBeforeInstruction(i8);
263fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
264fd4e5da5Sopenharmony_ci      ASSERT_EQ(1, available.size());
265fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
266fd4e5da5Sopenharmony_ci    }
267fd4e5da5Sopenharmony_ci    {
268fd4e5da5Sopenharmony_ci      auto available =
269fd4e5da5Sopenharmony_ci          integer_add_instructions.GetAvailableBeforeInstruction(i9);
270fd4e5da5Sopenharmony_ci      ASSERT_FALSE(available.empty());
271fd4e5da5Sopenharmony_ci      ASSERT_EQ(1, available.size());
272fd4e5da5Sopenharmony_ci      ASSERT_EQ(spv::Op::OpIAdd, available[0]->opcode());
273fd4e5da5Sopenharmony_ci    }
274fd4e5da5Sopenharmony_ci  }
275fd4e5da5Sopenharmony_ci}
276fd4e5da5Sopenharmony_ci
277fd4e5da5Sopenharmony_ciTEST(AvailableInstructionsTest, UnreachableBlock) {
278fd4e5da5Sopenharmony_ci  std::string shader = R"(
279fd4e5da5Sopenharmony_ci               OpCapability Shader
280fd4e5da5Sopenharmony_ci          %1 = OpExtInstImport "GLSL.std.450"
281fd4e5da5Sopenharmony_ci               OpMemoryModel Logical GLSL450
282fd4e5da5Sopenharmony_ci               OpEntryPoint Fragment %4 "main"
283fd4e5da5Sopenharmony_ci               OpExecutionMode %4 OriginUpperLeft
284fd4e5da5Sopenharmony_ci               OpSource ESSL 320
285fd4e5da5Sopenharmony_ci               OpName %4 "main"
286fd4e5da5Sopenharmony_ci               OpName %8 "x"
287fd4e5da5Sopenharmony_ci          %2 = OpTypeVoid
288fd4e5da5Sopenharmony_ci          %3 = OpTypeFunction %2
289fd4e5da5Sopenharmony_ci          %6 = OpTypeInt 32 1
290fd4e5da5Sopenharmony_ci          %7 = OpTypePointer Function %6
291fd4e5da5Sopenharmony_ci          %9 = OpConstant %6 2
292fd4e5da5Sopenharmony_ci          %4 = OpFunction %2 None %3
293fd4e5da5Sopenharmony_ci          %5 = OpLabel
294fd4e5da5Sopenharmony_ci          %8 = OpVariable %7 Function
295fd4e5da5Sopenharmony_ci               OpStore %8 %9
296fd4e5da5Sopenharmony_ci         %12 = OpLoad %6 %8
297fd4e5da5Sopenharmony_ci               OpReturn
298fd4e5da5Sopenharmony_ci         %10 = OpLabel
299fd4e5da5Sopenharmony_ci         %11 = OpLoad %6 %8
300fd4e5da5Sopenharmony_ci               OpReturn
301fd4e5da5Sopenharmony_ci               OpFunctionEnd
302fd4e5da5Sopenharmony_ci  )";
303fd4e5da5Sopenharmony_ci
304fd4e5da5Sopenharmony_ci  const auto env = SPV_ENV_UNIVERSAL_1_3;
305fd4e5da5Sopenharmony_ci  const auto consumer = nullptr;
306fd4e5da5Sopenharmony_ci  const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
307fd4e5da5Sopenharmony_ci  spvtools::ValidatorOptions validator_options;
308fd4e5da5Sopenharmony_ci  ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
309fd4e5da5Sopenharmony_ci                                               kConsoleMessageConsumer));
310fd4e5da5Sopenharmony_ci
311fd4e5da5Sopenharmony_ci  AvailableInstructions all_instructions(
312fd4e5da5Sopenharmony_ci      context.get(),
313fd4e5da5Sopenharmony_ci      [](opt::IRContext*, opt::Instruction*) -> bool { return true; });
314fd4e5da5Sopenharmony_ci  ASSERT_EQ(7, all_instructions
315fd4e5da5Sopenharmony_ci                   .GetAvailableBeforeInstruction(
316fd4e5da5Sopenharmony_ci                       context->get_def_use_mgr()->GetDef(12))
317fd4e5da5Sopenharmony_ci                   .size());
318fd4e5da5Sopenharmony_ci
319fd4e5da5Sopenharmony_ci#ifndef NDEBUG
320fd4e5da5Sopenharmony_ci  ASSERT_DEATH(all_instructions.GetAvailableBeforeInstruction(
321fd4e5da5Sopenharmony_ci                   context->get_def_use_mgr()->GetDef(11)),
322fd4e5da5Sopenharmony_ci               "Availability can only be queried for reachable instructions.");
323fd4e5da5Sopenharmony_ci#endif
324fd4e5da5Sopenharmony_ci}
325fd4e5da5Sopenharmony_ci
326fd4e5da5Sopenharmony_ci}  // namespace
327fd4e5da5Sopenharmony_ci}  // namespace fuzz
328fd4e5da5Sopenharmony_ci}  // namespace spvtools
329