• 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_permute_phi_operands.h"
16 
17 #include <vector>
18 
19 #include "source/fuzz/fuzzer_util.h"
20 
21 namespace spvtools {
22 namespace fuzz {
23 
TransformationPermutePhiOperands(protobufs::TransformationPermutePhiOperands message)24 TransformationPermutePhiOperands::TransformationPermutePhiOperands(
25     protobufs::TransformationPermutePhiOperands message)
26     : message_(std::move(message)) {}
27 
TransformationPermutePhiOperands(uint32_t result_id,const std::vector<uint32_t> & permutation)28 TransformationPermutePhiOperands::TransformationPermutePhiOperands(
29     uint32_t result_id, const std::vector<uint32_t>& permutation) {
30   message_.set_result_id(result_id);
31 
32   for (auto index : permutation) {
33     message_.add_permutation(index);
34   }
35 }
36 
IsApplicable(opt::IRContext * ir_context,const TransformationContext &) const37 bool TransformationPermutePhiOperands::IsApplicable(
38     opt::IRContext* ir_context, const TransformationContext& /*unused*/) const {
39   // Check that |message_.result_id| is valid.
40   const auto* inst =
41       ir_context->get_def_use_mgr()->GetDef(message_.result_id());
42   if (!inst || inst->opcode() != SpvOpPhi) {
43     return false;
44   }
45 
46   // Check that |message_.permutation| has expected size.
47   auto expected_permutation_size = inst->NumInOperands() / 2;
48   if (static_cast<uint32_t>(message_.permutation().size()) !=
49       expected_permutation_size) {
50     return false;
51   }
52 
53   // Check that |message_.permutation| has elements in range
54   // [0, expected_permutation_size - 1].
55   std::vector<uint32_t> permutation(message_.permutation().begin(),
56                                     message_.permutation().end());
57   assert(!fuzzerutil::HasDuplicates(permutation) &&
58          "Permutation has duplicates");
59 
60   // We must check whether the permutation is empty first because in that case
61   // |expected_permutation_size - 1| will produce
62   // |std::numeric_limits<uint32_t>::max()| since it's an unsigned integer.
63   return permutation.empty() ||
64          fuzzerutil::IsPermutationOfRange(permutation, 0,
65                                           expected_permutation_size - 1);
66 }
67 
Apply(opt::IRContext * ir_context,TransformationContext *) const68 void TransformationPermutePhiOperands::Apply(
69     opt::IRContext* ir_context, TransformationContext* /*unused*/) const {
70   auto* inst = ir_context->get_def_use_mgr()->GetDef(message_.result_id());
71   assert(inst);
72 
73   opt::Instruction::OperandList permuted_operands;
74   permuted_operands.reserve(inst->NumInOperands());
75 
76   for (auto index : message_.permutation()) {
77     permuted_operands.push_back(std::move(inst->GetInOperand(2 * index)));
78     permuted_operands.push_back(std::move(inst->GetInOperand(2 * index + 1)));
79   }
80 
81   inst->SetInOperands(std::move(permuted_operands));
82 
83   // Update the def-use manager.
84   ir_context->UpdateDefUse(inst);
85 }
86 
ToMessage() const87 protobufs::Transformation TransformationPermutePhiOperands::ToMessage() const {
88   protobufs::Transformation result;
89   *result.mutable_permute_phi_operands() = message_;
90   return result;
91 }
92 
GetFreshIds() const93 std::unordered_set<uint32_t> TransformationPermutePhiOperands::GetFreshIds()
94     const {
95   return std::unordered_set<uint32_t>();
96 }
97 
98 }  // namespace fuzz
99 }  // namespace spvtools
100