1fd4e5da5Sopenharmony_ci// Copyright (c) 2019 Google LLC
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/fuzzer_pass_merge_blocks.h"
16fd4e5da5Sopenharmony_ci
17fd4e5da5Sopenharmony_ci#include <vector>
18fd4e5da5Sopenharmony_ci
19fd4e5da5Sopenharmony_ci#include "source/fuzz/transformation_merge_blocks.h"
20fd4e5da5Sopenharmony_ci
21fd4e5da5Sopenharmony_cinamespace spvtools {
22fd4e5da5Sopenharmony_cinamespace fuzz {
23fd4e5da5Sopenharmony_ci
24fd4e5da5Sopenharmony_ciFuzzerPassMergeBlocks::FuzzerPassMergeBlocks(
25fd4e5da5Sopenharmony_ci    opt::IRContext* ir_context, TransformationContext* transformation_context,
26fd4e5da5Sopenharmony_ci    FuzzerContext* fuzzer_context,
27fd4e5da5Sopenharmony_ci    protobufs::TransformationSequence* transformations,
28fd4e5da5Sopenharmony_ci    bool ignore_inapplicable_transformations)
29fd4e5da5Sopenharmony_ci    : FuzzerPass(ir_context, transformation_context, fuzzer_context,
30fd4e5da5Sopenharmony_ci                 transformations, ignore_inapplicable_transformations) {}
31fd4e5da5Sopenharmony_ci
32fd4e5da5Sopenharmony_civoid FuzzerPassMergeBlocks::Apply() {
33fd4e5da5Sopenharmony_ci  // First we populate a sequence of transformations that we might consider
34fd4e5da5Sopenharmony_ci  // applying.
35fd4e5da5Sopenharmony_ci  std::vector<TransformationMergeBlocks> potential_transformations;
36fd4e5da5Sopenharmony_ci  // We do this by considering every block of every function.
37fd4e5da5Sopenharmony_ci  for (auto& function : *GetIRContext()->module()) {
38fd4e5da5Sopenharmony_ci    for (auto& block : function) {
39fd4e5da5Sopenharmony_ci      // We probabilistically decide to ignore some blocks.
40fd4e5da5Sopenharmony_ci      if (!GetFuzzerContext()->ChoosePercentage(
41fd4e5da5Sopenharmony_ci              GetFuzzerContext()->GetChanceOfMergingBlocks())) {
42fd4e5da5Sopenharmony_ci        continue;
43fd4e5da5Sopenharmony_ci      }
44fd4e5da5Sopenharmony_ci      // For other blocks, we add a transformation to merge the block into its
45fd4e5da5Sopenharmony_ci      // predecessor if that transformation would be applicable.
46fd4e5da5Sopenharmony_ci      TransformationMergeBlocks transformation(block.id());
47fd4e5da5Sopenharmony_ci      if (transformation.IsApplicable(GetIRContext(),
48fd4e5da5Sopenharmony_ci                                      *GetTransformationContext())) {
49fd4e5da5Sopenharmony_ci        potential_transformations.push_back(transformation);
50fd4e5da5Sopenharmony_ci      }
51fd4e5da5Sopenharmony_ci    }
52fd4e5da5Sopenharmony_ci  }
53fd4e5da5Sopenharmony_ci
54fd4e5da5Sopenharmony_ci  while (!potential_transformations.empty()) {
55fd4e5da5Sopenharmony_ci    auto transformation =
56fd4e5da5Sopenharmony_ci        GetFuzzerContext()->RemoveAtRandomIndex(&potential_transformations);
57fd4e5da5Sopenharmony_ci    MaybeApplyTransformation(transformation);
58fd4e5da5Sopenharmony_ci  }
59fd4e5da5Sopenharmony_ci}
60fd4e5da5Sopenharmony_ci
61fd4e5da5Sopenharmony_ci}  // namespace fuzz
62fd4e5da5Sopenharmony_ci}  // namespace spvtools
63