• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2020 Vasyl Teliman
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_swap_conditional_branch_operands.h"
16 
17 #include "gtest/gtest.h"
18 #include "source/fuzz/fuzzer_util.h"
19 #include "source/fuzz/instruction_descriptor.h"
20 #include "test/fuzz/fuzz_test_util.h"
21 
22 namespace spvtools {
23 namespace fuzz {
24 namespace {
25 
TEST(TransformationSwapConditionalBranchOperandsTest,BasicTest)26 TEST(TransformationSwapConditionalBranchOperandsTest, 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           %2 = OpTypeVoid
35           %3 = OpTypeFunction %2
36           %6 = OpTypeInt 32 1
37           %7 = OpTypePointer Function %6
38           %9 = OpConstant %6 0
39          %11 = OpConstant %6 1
40          %14 = OpTypeBool
41           %4 = OpFunction %2 None %3
42           %5 = OpLabel
43           %8 = OpVariable %7 Function
44          %10 = OpVariable %7 Function
45                OpStore %8 %9
46                OpStore %10 %11
47          %12 = OpLoad %6 %8
48          %13 = OpLoad %6 %10
49          %15 = OpSLessThan %14 %12 %13
50                OpSelectionMerge %17 None
51                OpBranchConditional %15 %16 %21 10 20
52          %16 = OpLabel
53          %18 = OpLoad %6 %10
54          %19 = OpLoad %6 %8
55          %20 = OpIAdd %6 %19 %18
56                OpBranch %17
57          %21 = OpLabel
58          %22 = OpLoad %6 %10
59          %23 = OpLoad %6 %8
60          %24 = OpISub %6 %23 %22
61                OpBranch %17
62          %17 = OpLabel
63          %25 = OpPhi %6 %20 %16 %24 %21
64                OpStore %8 %25
65                OpReturn
66                OpFunctionEnd
67   )";
68 
69   const auto env = SPV_ENV_UNIVERSAL_1_3;
70   const auto consumer = nullptr;
71   const auto context = BuildModule(env, consumer, shader, kFuzzAssembleOption);
72   spvtools::ValidatorOptions validator_options;
73   ASSERT_TRUE(fuzzerutil::IsValidAndWellFormed(context.get(), validator_options,
74                                                kConsoleMessageConsumer));
75   TransformationContext transformation_context(
76       MakeUnique<FactManager>(context.get()), validator_options);
77   // Invalid instruction descriptor.
78   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
79                    MakeInstructionDescriptor(26, SpvOpPhi, 0), 26)
80                    .IsApplicable(context.get(), transformation_context));
81 
82   // Descriptor for a wrong instruction.
83   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
84                    MakeInstructionDescriptor(25, SpvOpPhi, 0), 26)
85                    .IsApplicable(context.get(), transformation_context));
86 
87   // Fresh id is not fresh.
88   ASSERT_FALSE(TransformationSwapConditionalBranchOperands(
89                    MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 25)
90                    .IsApplicable(context.get(), transformation_context));
91 
92   TransformationSwapConditionalBranchOperands transformation(
93       MakeInstructionDescriptor(15, SpvOpBranchConditional, 0), 26);
94   ASSERT_EQ(nullptr, context->get_def_use_mgr()->GetDef(26));
95   ASSERT_EQ(nullptr, context->get_instr_block(26));
96   ASSERT_TRUE(
97       transformation.IsApplicable(context.get(), transformation_context));
98   ApplyAndCheckFreshIds(transformation, context.get(), &transformation_context);
99   ASSERT_EQ(SpvOpLogicalNot, context->get_def_use_mgr()->GetDef(26)->opcode());
100   ASSERT_EQ(5, context->get_instr_block(26)->id());
101   ASSERT_EQ(1, context->get_def_use_mgr()->NumUses(26));
102 
103   // Check that the def-use manager knows that the conditional branch operands
104   // have been swapped.
105   std::vector<std::pair<uint32_t, uint32_t>> phi_operand_to_new_operand_index =
106       {{16, 2}, {21, 1}};
107   for (std::pair<uint32_t, uint32_t>& entry :
108        phi_operand_to_new_operand_index) {
109     context->get_def_use_mgr()->WhileEachUse(
110         entry.first,
111         [&entry](opt::Instruction* inst, uint32_t operand_index) -> bool {
112           if (inst->opcode() == SpvOpBranchConditional) {
113             EXPECT_EQ(entry.second, operand_index);
114             return false;
115           }
116           return true;
117         });
118   }
119 
120   std::string after_transformation = R"(
121                OpCapability Shader
122           %1 = OpExtInstImport "GLSL.std.450"
123                OpMemoryModel Logical GLSL450
124                OpEntryPoint Fragment %4 "main"
125                OpExecutionMode %4 OriginUpperLeft
126                OpSource ESSL 310
127           %2 = OpTypeVoid
128           %3 = OpTypeFunction %2
129           %6 = OpTypeInt 32 1
130           %7 = OpTypePointer Function %6
131           %9 = OpConstant %6 0
132          %11 = OpConstant %6 1
133          %14 = OpTypeBool
134           %4 = OpFunction %2 None %3
135           %5 = OpLabel
136           %8 = OpVariable %7 Function
137          %10 = OpVariable %7 Function
138                OpStore %8 %9
139                OpStore %10 %11
140          %12 = OpLoad %6 %8
141          %13 = OpLoad %6 %10
142          %15 = OpSLessThan %14 %12 %13
143          %26 = OpLogicalNot %14 %15
144                OpSelectionMerge %17 None
145                OpBranchConditional %26 %21 %16 20 10
146          %16 = OpLabel
147          %18 = OpLoad %6 %10
148          %19 = OpLoad %6 %8
149          %20 = OpIAdd %6 %19 %18
150                OpBranch %17
151          %21 = OpLabel
152          %22 = OpLoad %6 %10
153          %23 = OpLoad %6 %8
154          %24 = OpISub %6 %23 %22
155                OpBranch %17
156          %17 = OpLabel
157          %25 = OpPhi %6 %20 %16 %24 %21
158                OpStore %8 %25
159                OpReturn
160                OpFunctionEnd
161   )";
162 
163   ASSERT_TRUE(IsEqual(env, after_transformation, context.get()));
164 }
165 
166 }  // namespace
167 }  // namespace fuzz
168 }  // namespace spvtools
169