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