blob: d468e41d1eeb74cf20fa6c5bfe0122cb173a9e9f [file] [log] [blame]
Ben Claytond552f632019-11-18 11:18:41 +00001// Copyright (c) 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#include "source/fuzz/transformation_composite_extract.h"
Alexis Hetuc00ee6c2020-07-27 10:48:25 -040016
Alexis Hetu3eb4dd82020-10-29 21:37:20 -040017#include "gtest/gtest.h"
18#include "source/fuzz/fuzzer_util.h"
Ben Claytond552f632019-11-18 11:18:41 +000019#include "source/fuzz/instruction_descriptor.h"
20#include "test/fuzz/fuzz_test_util.h"
21
22namespace spvtools {
23namespace fuzz {
24namespace {
25
26TEST(TransformationCompositeExtractTest, BasicTest) {
27 std::string shader = R"(
28 OpCapability Shader
29 %1 = OpExtInstImport "GLSL.std.450"
30 OpMemoryModel Logical GLSL450
31 OpEntryPoint Fragment %4 "main"
32 OpExecutionMode %4 OriginUpperLeft
33 OpSource ESSL 310
34 OpName %4 "main"
35 OpName %8 "a"
36 OpName %10 "b"
37 OpName %17 "FunnyPoint"
38 OpMemberName %17 0 "x"
39 OpMemberName %17 1 "y"
40 OpMemberName %17 2 "z"
41 OpName %19 "p"
42 %2 = OpTypeVoid
43 %3 = OpTypeFunction %2
44 %6 = OpTypeInt 32 1
45 %7 = OpTypePointer Function %6
46 %12 = OpTypeBool
47 %16 = OpTypeFloat 32
48 %17 = OpTypeStruct %16 %16 %6
49 %81 = OpTypeStruct %17 %16
50 %18 = OpTypePointer Function %17
51 %20 = OpConstant %6 0
52 %23 = OpTypePointer Function %16
53 %26 = OpConstant %6 1
54 %30 = OpConstant %6 2
55 %80 = OpUndef %16
56 %4 = OpFunction %2 None %3
57 %5 = OpLabel
58 %8 = OpVariable %7 Function
59 %10 = OpVariable %7 Function
60 %19 = OpVariable %18 Function
61 %9 = OpLoad %6 %8
62 %11 = OpLoad %6 %10
63 %100 = OpCompositeConstruct %17 %80 %80 %26
64 %104 = OpCompositeConstruct %81 %100 %80
65 %13 = OpIEqual %12 %9 %11
66 OpSelectionMerge %15 None
67 OpBranchConditional %13 %14 %25
68 %14 = OpLabel
69 %21 = OpLoad %6 %8
70 %22 = OpConvertSToF %16 %21
71 %101 = OpCompositeConstruct %17 %22 %80 %30
72 %24 = OpAccessChain %23 %19 %20
73 OpStore %24 %22
74 OpBranch %15
75 %25 = OpLabel
76 %27 = OpLoad %6 %10
77 %28 = OpConvertSToF %16 %27
78 %102 = OpCompositeConstruct %17 %80 %28 %27
79 %29 = OpAccessChain %23 %19 %26
80 OpStore %29 %28
81 OpBranch %15
82 %15 = OpLabel
83 %31 = OpAccessChain %23 %19 %20
84 %32 = OpLoad %16 %31
85 %33 = OpAccessChain %23 %19 %26
86 %34 = OpLoad %16 %33
87 %103 = OpCompositeConstruct %17 %34 %32 %9
88 %35 = OpFAdd %16 %32 %34
89 %36 = OpConvertFToS %6 %35
90 %37 = OpAccessChain %7 %19 %30
91 OpStore %37 %36
92 OpReturn
93 OpFunctionEnd
94 )";
95
96 const auto env = SPV_ENV_UNIVERSAL_1_4;
97 const auto consumer = nullptr;
98 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
Ben Clayton38e46912020-05-26 15:56:15 +010099 spvtools::ValidatorOptions validator_options;
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400100 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
101 kConsoleMessageConsumer));
102 TransformationContext transformation_context(
103 MakeUnique<FactManager>(context.get()), validator_options);
Ben Claytond552f632019-11-18 11:18:41 +0000104 // Instruction does not exist.
Nicolas Capens84c9c452022-11-18 14:11:05 +0000105 ASSERT_FALSE(
106 TransformationCompositeExtract(
107 MakeInstructionDescriptor(36, spv::Op::OpIAdd, 0), 200, 101, {0})
108 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000109
110 // Id for composite is not a composite.
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400111 ASSERT_FALSE(
112 TransformationCompositeExtract(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000113 MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 200, 32, {})
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400114 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000115
116 // Composite does not dominate instruction being inserted before.
Nicolas Capens84c9c452022-11-18 14:11:05 +0000117 ASSERT_FALSE(TransformationCompositeExtract(
118 MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0),
119 200, 101, {0})
120 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000121
122 // Too many indices for extraction from struct composite.
Nicolas Capens84c9c452022-11-18 14:11:05 +0000123 ASSERT_FALSE(TransformationCompositeExtract(
124 MakeInstructionDescriptor(24, spv::Op::OpAccessChain, 0),
125 200, 101, {0, 0})
126 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000127
128 // Too many indices for extraction from struct composite.
Nicolas Capens84c9c452022-11-18 14:11:05 +0000129 ASSERT_FALSE(TransformationCompositeExtract(
130 MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200,
131 104, {0, 0, 0})
132 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000133
134 // Out of bounds index for extraction from struct composite.
135 ASSERT_FALSE(
136 TransformationCompositeExtract(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000137 MakeInstructionDescriptor(13, spv::Op::OpIEqual, 0), 200, 104, {0, 3})
Ben Clayton38e46912020-05-26 15:56:15 +0100138 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000139
140 // Result id already used.
Nicolas Capens84c9c452022-11-18 14:11:05 +0000141 ASSERT_FALSE(
142 TransformationCompositeExtract(
143 MakeInstructionDescriptor(35, spv::Op::OpFAdd, 0), 80, 103, {0})
144 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000145
146 TransformationCompositeExtract transformation_1(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000147 MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
Alexis Hetu00e0af12021-11-08 08:57:46 -0500148 ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(201));
149 ASSERT_EQ(nullptr, context->get_instr_block(201));
150 uint32_t num_uses_of_100_before = context->get_def_use_mgr()->NumUses(100);
Ben Clayton38e46912020-05-26 15:56:15 +0100151 ASSERT_TRUE(
152 transformation_1.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400153 ApplyAndCheckFreshIds(transformation_1, context.get(),
154 &transformation_context);
Nicolas Capens84c9c452022-11-18 14:11:05 +0000155 ASSERT_EQ(spv::Op::OpCompositeExtract,
Alexis Hetu00e0af12021-11-08 08:57:46 -0500156 context->get_def_use_mgr()->GetDef(201)->opcode());
157 ASSERT_EQ(15, context->get_instr_block(201)->id());
158 ASSERT_EQ(num_uses_of_100_before + 1,
159 context->get_def_use_mgr()->NumUses(100));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400160 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
161 kConsoleMessageConsumer));
Ben Claytond552f632019-11-18 11:18:41 +0000162
163 TransformationCompositeExtract transformation_2(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000164 MakeInstructionDescriptor(37, spv::Op::OpAccessChain, 0), 202, 104,
165 {0, 2});
Ben Clayton38e46912020-05-26 15:56:15 +0100166 ASSERT_TRUE(
167 transformation_2.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400168 ApplyAndCheckFreshIds(transformation_2, context.get(),
169 &transformation_context);
170 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
171 kConsoleMessageConsumer));
Ben Claytond552f632019-11-18 11:18:41 +0000172
173 TransformationCompositeExtract transformation_3(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000174 MakeInstructionDescriptor(29, spv::Op::OpAccessChain, 0), 203, 104, {0});
Ben Clayton38e46912020-05-26 15:56:15 +0100175 ASSERT_TRUE(
176 transformation_3.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400177 ApplyAndCheckFreshIds(transformation_3, context.get(),
178 &transformation_context);
179 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
180 kConsoleMessageConsumer));
Ben Claytond552f632019-11-18 11:18:41 +0000181
182 TransformationCompositeExtract transformation_4(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000183 MakeInstructionDescriptor(24, spv::Op::OpStore, 0), 204, 101, {0});
Ben Clayton38e46912020-05-26 15:56:15 +0100184 ASSERT_TRUE(
185 transformation_4.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400186 ApplyAndCheckFreshIds(transformation_4, context.get(),
187 &transformation_context);
188 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
189 kConsoleMessageConsumer));
Ben Claytond552f632019-11-18 11:18:41 +0000190
191 TransformationCompositeExtract transformation_5(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000192 MakeInstructionDescriptor(29, spv::Op::OpBranch, 0), 205, 102, {2});
Ben Clayton38e46912020-05-26 15:56:15 +0100193 ASSERT_TRUE(
194 transformation_5.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400195 ApplyAndCheckFreshIds(transformation_5, context.get(),
196 &transformation_context);
197 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
198 kConsoleMessageConsumer));
Ben Claytond552f632019-11-18 11:18:41 +0000199
200 TransformationCompositeExtract transformation_6(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000201 MakeInstructionDescriptor(37, spv::Op::OpReturn, 0), 206, 103, {1});
Ben Clayton38e46912020-05-26 15:56:15 +0100202 ASSERT_TRUE(
203 transformation_6.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400204 ApplyAndCheckFreshIds(transformation_6, context.get(),
205 &transformation_context);
206 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
207 kConsoleMessageConsumer));
Ben Claytond552f632019-11-18 11:18:41 +0000208
Ben Clayton38e46912020-05-26 15:56:15 +0100209 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
210 MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
211 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
212 MakeDataDescriptor(202, {}), MakeDataDescriptor(104, {0, 2})));
213 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
214 MakeDataDescriptor(203, {}), MakeDataDescriptor(104, {0})));
215 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
216 MakeDataDescriptor(204, {}), MakeDataDescriptor(101, {0})));
217 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
218 MakeDataDescriptor(205, {}), MakeDataDescriptor(102, {2})));
219 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
220 MakeDataDescriptor(206, {}), MakeDataDescriptor(103, {1})));
Ben Claytond552f632019-11-18 11:18:41 +0000221
222 std::string after_transformation = R"(
223 OpCapability Shader
224 %1 = OpExtInstImport "GLSL.std.450"
225 OpMemoryModel Logical GLSL450
226 OpEntryPoint Fragment %4 "main"
227 OpExecutionMode %4 OriginUpperLeft
228 OpSource ESSL 310
229 OpName %4 "main"
230 OpName %8 "a"
231 OpName %10 "b"
232 OpName %17 "FunnyPoint"
233 OpMemberName %17 0 "x"
234 OpMemberName %17 1 "y"
235 OpMemberName %17 2 "z"
236 OpName %19 "p"
237 %2 = OpTypeVoid
238 %3 = OpTypeFunction %2
239 %6 = OpTypeInt 32 1
240 %7 = OpTypePointer Function %6
241 %12 = OpTypeBool
242 %16 = OpTypeFloat 32
243 %17 = OpTypeStruct %16 %16 %6
244 %81 = OpTypeStruct %17 %16
245 %18 = OpTypePointer Function %17
246 %20 = OpConstant %6 0
247 %23 = OpTypePointer Function %16
248 %26 = OpConstant %6 1
249 %30 = OpConstant %6 2
250 %80 = OpUndef %16
251 %4 = OpFunction %2 None %3
252 %5 = OpLabel
253 %8 = OpVariable %7 Function
254 %10 = OpVariable %7 Function
255 %19 = OpVariable %18 Function
256 %9 = OpLoad %6 %8
257 %11 = OpLoad %6 %10
258 %100 = OpCompositeConstruct %17 %80 %80 %26
259 %104 = OpCompositeConstruct %81 %100 %80
260 %13 = OpIEqual %12 %9 %11
261 OpSelectionMerge %15 None
262 OpBranchConditional %13 %14 %25
263 %14 = OpLabel
264 %21 = OpLoad %6 %8
265 %22 = OpConvertSToF %16 %21
266 %101 = OpCompositeConstruct %17 %22 %80 %30
267 %24 = OpAccessChain %23 %19 %20
268 %204 = OpCompositeExtract %16 %101 0
269 OpStore %24 %22
270 OpBranch %15
271 %25 = OpLabel
272 %27 = OpLoad %6 %10
273 %28 = OpConvertSToF %16 %27
274 %102 = OpCompositeConstruct %17 %80 %28 %27
275 %203 = OpCompositeExtract %17 %104 0
276 %29 = OpAccessChain %23 %19 %26
277 OpStore %29 %28
278 %205 = OpCompositeExtract %6 %102 2
279 OpBranch %15
280 %15 = OpLabel
281 %31 = OpAccessChain %23 %19 %20
282 %32 = OpLoad %16 %31
283 %33 = OpAccessChain %23 %19 %26
284 %34 = OpLoad %16 %33
285 %103 = OpCompositeConstruct %17 %34 %32 %9
286 %35 = OpFAdd %16 %32 %34
287 %201 = OpCompositeExtract %6 %100 2
288 %36 = OpConvertFToS %6 %35
289 %202 = OpCompositeExtract %6 %104 0 2
290 %37 = OpAccessChain %7 %19 %30
291 OpStore %37 %36
292 %206 = OpCompositeExtract %16 %103 1
293 OpReturn
294 OpFunctionEnd
295 )";
296 ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
297}
298
299TEST(TransformationCompositeExtractTest, IllegalInsertionPoints) {
300 std::string shader = R"(
301 OpCapability Shader
302 %1 = OpExtInstImport "GLSL.std.450"
303 OpMemoryModel Logical GLSL450
304 OpEntryPoint Fragment %4 "main" %51 %27
305 OpExecutionMode %4 OriginUpperLeft
306 OpSource ESSL 310
307 OpName %4 "main"
308 OpName %25 "buf"
309 OpMemberName %25 0 "value"
310 OpName %27 ""
311 OpName %51 "color"
312 OpMemberDecorate %25 0 Offset 0
313 OpDecorate %25 Block
314 OpDecorate %27 DescriptorSet 0
315 OpDecorate %27 Binding 0
316 OpDecorate %51 Location 0
317 %2 = OpTypeVoid
318 %3 = OpTypeFunction %2
319 %6 = OpTypeFloat 32
320 %7 = OpTypeVector %6 4
321 %10 = OpConstant %6 0.300000012
322 %11 = OpConstant %6 0.400000006
323 %12 = OpConstant %6 0.5
324 %13 = OpConstant %6 1
325 %14 = OpConstantComposite %7 %10 %11 %12 %13
326 %15 = OpTypeInt 32 1
327 %18 = OpConstant %15 0
328 %25 = OpTypeStruct %6
329 %26 = OpTypePointer Uniform %25
330 %27 = OpVariable %26 Uniform
331 %28 = OpTypePointer Uniform %6
332 %32 = OpTypeBool
333 %103 = OpConstantTrue %32
334 %34 = OpConstant %6 0.100000001
335 %48 = OpConstant %15 1
336 %50 = OpTypePointer Output %7
337 %51 = OpVariable %50 Output
338 %100 = OpTypePointer Function %6
339 %4 = OpFunction %2 None %3
340 %5 = OpLabel
341 %101 = OpVariable %100 Function
342 %102 = OpVariable %100 Function
343 OpBranch %19
344 %19 = OpLabel
345 %60 = OpPhi %7 %14 %5 %58 %20
346 %59 = OpPhi %15 %18 %5 %49 %20
347 %29 = OpAccessChain %28 %27 %18
348 %30 = OpLoad %6 %29
349 %31 = OpConvertFToS %15 %30
350 %33 = OpSLessThan %32 %59 %31
351 OpLoopMerge %21 %20 None
352 OpBranchConditional %33 %20 %21
353 %20 = OpLabel
354 %39 = OpCompositeExtract %6 %60 0
355 %40 = OpFAdd %6 %39 %34
356 %55 = OpCompositeInsert %7 %40 %60 0
357 %44 = OpCompositeExtract %6 %60 1
358 %45 = OpFSub %6 %44 %34
359 %58 = OpCompositeInsert %7 %45 %55 1
360 %49 = OpIAdd %15 %59 %48
361 OpBranch %19
362 %21 = OpLabel
363 OpStore %51 %60
364 OpSelectionMerge %105 None
365 OpBranchConditional %103 %104 %105
366 %104 = OpLabel
367 OpBranch %105
368 %105 = OpLabel
369 OpReturn
370 OpFunctionEnd
371 )";
372
373 const auto env = SPV_ENV_UNIVERSAL_1_4;
374 const auto consumer = nullptr;
375 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
Ben Clayton38e46912020-05-26 15:56:15 +0100376 spvtools::ValidatorOptions validator_options;
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400377 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
378 kConsoleMessageConsumer));
379 TransformationContext transformation_context(
380 MakeUnique<FactManager>(context.get()), validator_options);
Ben Claytond552f632019-11-18 11:18:41 +0000381 // Cannot insert before the OpVariables of a function.
382 ASSERT_FALSE(
383 TransformationCompositeExtract(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000384 MakeInstructionDescriptor(101, spv::Op::OpVariable, 0), 200, 14, {0})
Ben Clayton38e46912020-05-26 15:56:15 +0100385 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000386 ASSERT_FALSE(
387 TransformationCompositeExtract(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000388 MakeInstructionDescriptor(101, spv::Op::OpVariable, 1), 200, 14, {1})
Ben Clayton38e46912020-05-26 15:56:15 +0100389 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000390 ASSERT_FALSE(
391 TransformationCompositeExtract(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000392 MakeInstructionDescriptor(102, spv::Op::OpVariable, 0), 200, 14, {1})
Ben Clayton38e46912020-05-26 15:56:15 +0100393 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000394 // OK to insert right after the OpVariables.
Nicolas Capens84c9c452022-11-18 14:11:05 +0000395 ASSERT_FALSE(
Ben Claytond552f632019-11-18 11:18:41 +0000396 TransformationCompositeExtract(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000397 MakeInstructionDescriptor(102, spv::Op::OpBranch, 1), 200, 14, {1})
Ben Clayton38e46912020-05-26 15:56:15 +0100398 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000399
Nicolas Capens84c9c452022-11-18 14:11:05 +0000400 // Cannot insert before the OpPhis of a block.
401 ASSERT_FALSE(
402 TransformationCompositeExtract(
403 MakeInstructionDescriptor(60, spv::Op::OpPhi, 0), 200, 14, {2})
404 .IsApplicable(context.get(), transformation_context));
405 ASSERT_FALSE(
406 TransformationCompositeExtract(
407 MakeInstructionDescriptor(59, spv::Op::OpPhi, 0), 200, 14, {3})
408 .IsApplicable(context.get(), transformation_context));
409 // OK to insert after the OpPhis.
410 ASSERT_TRUE(TransformationCompositeExtract(
411 MakeInstructionDescriptor(59, spv::Op::OpAccessChain, 0), 200,
412 14, {3})
413 .IsApplicable(context.get(), transformation_context));
414
Ben Claytond552f632019-11-18 11:18:41 +0000415 // Cannot insert before OpLoopMerge
Nicolas Capens84c9c452022-11-18 14:11:05 +0000416 ASSERT_FALSE(
417 TransformationCompositeExtract(
418 MakeInstructionDescriptor(33, spv::Op::OpBranchConditional, 0), 200,
419 14, {3})
420 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000421
422 // Cannot insert before OpSelectionMerge
Nicolas Capens84c9c452022-11-18 14:11:05 +0000423 ASSERT_FALSE(
424 TransformationCompositeExtract(
425 MakeInstructionDescriptor(21, spv::Op::OpBranchConditional, 0), 200,
426 14, {2})
427 .IsApplicable(context.get(), transformation_context));
Ben Claytond552f632019-11-18 11:18:41 +0000428}
429
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400430TEST(TransformationCompositeExtractTest, AddSynonymsForRelevantIds) {
431 std::string shader = R"(
432 OpCapability Shader
433 %1 = OpExtInstImport "GLSL.std.450"
434 OpMemoryModel Logical GLSL450
435 OpEntryPoint Fragment %4 "main"
436 OpExecutionMode %4 OriginUpperLeft
437 OpSource ESSL 310
438 OpName %4 "main"
439 OpName %8 "a"
440 OpName %10 "b"
441 OpName %17 "FunnyPoint"
442 OpMemberName %17 0 "x"
443 OpMemberName %17 1 "y"
444 OpMemberName %17 2 "z"
445 OpName %19 "p"
446 %2 = OpTypeVoid
447 %3 = OpTypeFunction %2
448 %6 = OpTypeInt 32 1
449 %7 = OpTypePointer Function %6
450 %12 = OpTypeBool
451 %16 = OpTypeFloat 32
452 %17 = OpTypeStruct %16 %16 %6
453 %81 = OpTypeStruct %17 %16
454 %18 = OpTypePointer Function %17
455 %20 = OpConstant %6 0
456 %23 = OpTypePointer Function %16
457 %26 = OpConstant %6 1
458 %30 = OpConstant %6 2
459 %80 = OpUndef %16
460 %4 = OpFunction %2 None %3
461 %5 = OpLabel
462 %8 = OpVariable %7 Function
463 %10 = OpVariable %7 Function
464 %19 = OpVariable %18 Function
465 %9 = OpLoad %6 %8
466 %11 = OpLoad %6 %10
467 %100 = OpCompositeConstruct %17 %80 %80 %26
468 %104 = OpCompositeConstruct %81 %100 %80
469 %13 = OpIEqual %12 %9 %11
470 OpSelectionMerge %15 None
471 OpBranchConditional %13 %14 %25
472 %14 = OpLabel
473 %21 = OpLoad %6 %8
474 %22 = OpConvertSToF %16 %21
475 %101 = OpCompositeConstruct %17 %22 %80 %30
476 %24 = OpAccessChain %23 %19 %20
477 OpStore %24 %22
478 OpBranch %15
479 %25 = OpLabel
480 %27 = OpLoad %6 %10
481 %28 = OpConvertSToF %16 %27
482 %102 = OpCompositeConstruct %17 %80 %28 %27
483 %29 = OpAccessChain %23 %19 %26
484 OpStore %29 %28
485 OpBranch %15
486 %15 = OpLabel
487 %31 = OpAccessChain %23 %19 %20
488 %32 = OpLoad %16 %31
489 %33 = OpAccessChain %23 %19 %26
490 %34 = OpLoad %16 %33
491 %103 = OpCompositeConstruct %17 %34 %32 %9
492 %35 = OpFAdd %16 %32 %34
493 %36 = OpConvertFToS %6 %35
494 %37 = OpAccessChain %7 %19 %30
495 OpStore %37 %36
496 OpReturn
497 OpFunctionEnd
498 )";
499
500 const auto env = SPV_ENV_UNIVERSAL_1_4;
501 const auto consumer = nullptr;
502 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400503 spvtools::ValidatorOptions validator_options;
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400504 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
505 kConsoleMessageConsumer));
506 TransformationContext transformation_context(
507 MakeUnique<FactManager>(context.get()), validator_options);
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400508 TransformationCompositeExtract transformation(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000509 MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400510 ASSERT_TRUE(
511 transformation.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400512 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
513 ASSERT_TRUE(transformation_context.GetFactManager()->IsSynonymous(
514 MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400515}
516
517TEST(TransformationCompositeExtractTest, DontAddSynonymsForIrrelevantIds) {
518 std::string shader = R"(
519 OpCapability Shader
520 %1 = OpExtInstImport "GLSL.std.450"
521 OpMemoryModel Logical GLSL450
522 OpEntryPoint Fragment %4 "main"
523 OpExecutionMode %4 OriginUpperLeft
524 OpSource ESSL 310
525 OpName %4 "main"
526 OpName %8 "a"
527 OpName %10 "b"
528 OpName %17 "FunnyPoint"
529 OpMemberName %17 0 "x"
530 OpMemberName %17 1 "y"
531 OpMemberName %17 2 "z"
532 OpName %19 "p"
533 %2 = OpTypeVoid
534 %3 = OpTypeFunction %2
535 %6 = OpTypeInt 32 1
536 %7 = OpTypePointer Function %6
537 %12 = OpTypeBool
538 %16 = OpTypeFloat 32
539 %17 = OpTypeStruct %16 %16 %6
540 %81 = OpTypeStruct %17 %16
541 %18 = OpTypePointer Function %17
542 %20 = OpConstant %6 0
543 %23 = OpTypePointer Function %16
544 %26 = OpConstant %6 1
545 %30 = OpConstant %6 2
546 %80 = OpUndef %16
547 %4 = OpFunction %2 None %3
548 %5 = OpLabel
549 %8 = OpVariable %7 Function
550 %10 = OpVariable %7 Function
551 %19 = OpVariable %18 Function
552 %9 = OpLoad %6 %8
553 %11 = OpLoad %6 %10
554 %100 = OpCompositeConstruct %17 %80 %80 %26
555 %104 = OpCompositeConstruct %81 %100 %80
556 %13 = OpIEqual %12 %9 %11
557 OpSelectionMerge %15 None
558 OpBranchConditional %13 %14 %25
559 %14 = OpLabel
560 %21 = OpLoad %6 %8
561 %22 = OpConvertSToF %16 %21
562 %101 = OpCompositeConstruct %17 %22 %80 %30
563 %24 = OpAccessChain %23 %19 %20
564 OpStore %24 %22
565 OpBranch %15
566 %25 = OpLabel
567 %27 = OpLoad %6 %10
568 %28 = OpConvertSToF %16 %27
569 %102 = OpCompositeConstruct %17 %80 %28 %27
570 %29 = OpAccessChain %23 %19 %26
571 OpStore %29 %28
572 OpBranch %15
573 %15 = OpLabel
574 %31 = OpAccessChain %23 %19 %20
575 %32 = OpLoad %16 %31
576 %33 = OpAccessChain %23 %19 %26
577 %34 = OpLoad %16 %33
578 %103 = OpCompositeConstruct %17 %34 %32 %9
579 %35 = OpFAdd %16 %32 %34
580 %36 = OpConvertFToS %6 %35
581 %37 = OpAccessChain %7 %19 %30
582 OpStore %37 %36
583 OpReturn
584 OpFunctionEnd
585 )";
586
587 const auto env = SPV_ENV_UNIVERSAL_1_4;
588 const auto consumer = nullptr;
589 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400590 spvtools::ValidatorOptions validator_options;
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400591 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
592 kConsoleMessageConsumer));
593 TransformationContext transformation_context(
594 MakeUnique<FactManager>(context.get()), validator_options);
595 transformation_context.GetFactManager()->AddFactIdIsIrrelevant(100);
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400596 TransformationCompositeExtract transformation(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000597 MakeInstructionDescriptor(36, spv::Op::OpConvertFToS, 0), 201, 100, {2});
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400598 ASSERT_TRUE(
599 transformation.IsApplicable(context.get(), transformation_context));
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400600 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
601 ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
602 MakeDataDescriptor(201, {}), MakeDataDescriptor(100, {2})));
603}
604
605TEST(TransformationCompositeExtractTest, DontAddSynonymInDeadBlock) {
606 std::string shader = R"(
607 OpCapability Shader
608 %1 = OpExtInstImport "GLSL.std.450"
609 OpMemoryModel Logical GLSL450
610 OpEntryPoint Fragment %4 "main"
611 OpExecutionMode %4 OriginUpperLeft
612 OpSource ESSL 320
613 %2 = OpTypeVoid
614 %3 = OpTypeFunction %2
615 %6 = OpTypeInt 32 1
616 %7 = OpTypeVector %6 2
617 %8 = OpTypePointer Function %7
618 %10 = OpConstant %6 0
619 %11 = OpConstant %6 1
620 %12 = OpConstantComposite %7 %10 %11
621 %13 = OpTypeBool
622 %14 = OpConstantFalse %13
623 %4 = OpFunction %2 None %3
624 %5 = OpLabel
625 %9 = OpVariable %8 Function
626 OpStore %9 %12
627 OpSelectionMerge %16 None
628 OpBranchConditional %14 %15 %16
629 %15 = OpLabel
630 OpBranch %16
631 %16 = OpLabel
632 OpReturn
633 OpFunctionEnd
634 )";
635
636 const auto env = SPV_ENV_UNIVERSAL_1_4;
637 const auto consumer = nullptr;
638 const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
639 spvtools::ValidatorOptions validator_options;
640 ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
641 kConsoleMessageConsumer));
642 TransformationContext transformation_context(
643 MakeUnique<FactManager>(context.get()), validator_options);
644 transformation_context.GetFactManager()->AddFactBlockIsDead(15);
645 TransformationCompositeExtract transformation(
Nicolas Capens84c9c452022-11-18 14:11:05 +0000646 MakeInstructionDescriptor(15, spv::Op::OpBranch, 0), 100, 12, {0});
Alexis Hetu3eb4dd82020-10-29 21:37:20 -0400647 ASSERT_TRUE(
648 transformation.IsApplicable(context.get(), transformation_context));
649 ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
650 ASSERT_FALSE(transformation_context.GetFactManager()->IsSynonymous(
651 MakeDataDescriptor(100, {}), MakeDataDescriptor(12, {0})));
Alexis Hetuc00ee6c2020-07-27 10:48:25 -0400652}
653
Ben Claytond552f632019-11-18 11:18:41 +0000654} // namespace
655} // namespace fuzz
656} // namespace spvtools