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 #ifndef SOURCE_FUZZ_TRANSFORMATION_WRAP_REGION_IN_SELECTION_H_
16 #define SOURCE_FUZZ_TRANSFORMATION_WRAP_REGION_IN_SELECTION_H_
17 
18 #include "source/fuzz/protobufs/spirvfuzz_protobufs.h"
19 #include "source/fuzz/transformation.h"
20 #include "source/fuzz/transformation_context.h"
21 #include "source/opt/ir_context.h"
22 
23 namespace spvtools {
24 namespace fuzz {
25 
26 class TransformationWrapRegionInSelection : public Transformation {
27  public:
28   explicit TransformationWrapRegionInSelection(
29       const protobufs::TransformationWrapRegionInSelection& message);
30 
31   TransformationWrapRegionInSelection(uint32_t region_entry_block_id,
32                                       uint32_t region_exit_block_id,
33                                       bool branch_condition);
34 
35   // - It should be possible to apply this transformation to a
36   //   single-exit-single-entry region of blocks dominated by
37   //   |region_entry_block_id| and postdominated by |region_exit_block_id|
38   //   (see IsApplicableToBlockRange method for further details).
39   //
40   //   TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/3828):
41   //    Consider applying this transformation to non-single-entry-single-exit
42   //    regions of blocks.
43   // - There must exist an irrelevant boolean constant with value
44   //   |branch_condition|.
45   bool IsApplicable(
46       opt::IRContext* ir_context,
47       const TransformationContext& transformation_context) const override;
48 
49   // - Transforms |region_entry_block_id| into a selection header with both
50   //   branches pointing to the block's successor.
51   // - |branch_condition| is used as a condition in the header's
52   //   OpBranchConditional instruction.
53   // - Transforms |region_exit_block_id| into a merge block of the selection's
54   //   header.
55   void Apply(opt::IRContext* ir_context,
56              TransformationContext* transformation_context) const override;
57 
58   protobufs::Transformation ToMessage() const override;
59 
60   // Returns true if it's possible to apply this transformation to the
61   // single-exit-single-entry region of blocks starting with
62   // |header_block_candidate_id| and ending with |merge_block_candidate_id|.
63   // Concretely:
64   // - Both |header_block_candidate_id| and |merge_block_candidate_id| must be
65   //   result ids of some blocks in the module.
66   // - Both blocks must belong to the same function.
67   // - |header_block_candidate_id| must strictly dominate
68   //   |merge_block_candidate_id| and |merge_block_candidate_id| must strictly
69   //   postdominate |header_block_candidate_id|.
70   // - |header_block_candidate_id| can't be a header block of any construct.
71   // - |header_block_candidate_id|'s terminator must be an OpBranch.
72   // - |merge_block_candidate_id| can't be a merge block of any other construct.
73   // - Both |header_block_candidate_id| and |merge_block_candidate_id| must be
74   //   inside the same construct if any.
75   static bool IsApplicableToBlockRange(opt::IRContext* ir_context,
76                                        uint32_t header_block_candidate_id,
77                                        uint32_t merge_block_candidate_id);
78 
79   std::unordered_set<uint32_t> GetFreshIds() const override;
80 
81  private:
82   protobufs::TransformationWrapRegionInSelection message_;
83 };
84 
85 }  // namespace fuzz
86 }  // namespace spvtools
87 
88 #endif  // SOURCE_FUZZ_TRANSFORMATION_WRAP_REGION_IN_SELECTION_H_
89