1 // Copyright (c) 2020 Google LLC 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_DUPLICATE_REGION_WITH_SELECTION_H_ 16 #define SOURCE_FUZZ_TRANSFORMATION_DUPLICATE_REGION_WITH_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 TransformationDuplicateRegionWithSelection : public Transformation { 27 public: 28 explicit TransformationDuplicateRegionWithSelection( 29 protobufs::TransformationDuplicateRegionWithSelection message); 30 31 explicit TransformationDuplicateRegionWithSelection( 32 uint32_t new_entry_fresh_id, uint32_t condition_id, 33 uint32_t merge_label_fresh_id, uint32_t entry_block_id, 34 uint32_t exit_block_id, 35 const std::map<uint32_t, uint32_t>& original_label_to_duplicate_label, 36 const std::map<uint32_t, uint32_t>& original_id_to_duplicate_id, 37 const std::map<uint32_t, uint32_t>& original_id_to_phi_id); 38 39 // - |new_entry_fresh_id|, |merge_label_fresh_id| must be fresh and distinct. 40 // - |condition_id| must refer to a valid instruction of boolean type. 41 // - |entry_block_id| and |exit_block_id| must refer to valid blocks and they 42 // must form a single-entry, single-exit region. Its constructs and their 43 // merge blocks must be either wholly within or wholly outside of the 44 // region. 45 // - |original_label_to_duplicate_label| must contain at least a key for every 46 // block in the original region. 47 // - |original_id_to_duplicate_id| must contain at least a key for every 48 // result id in the original region. 49 // - |original_id_to_phi_id| must contain at least a key for every result id 50 // available at the end of the original region. 51 // - In each of these three maps, each value must be a distinct, fresh id. 52 bool IsApplicable( 53 opt::IRContext* ir_context, 54 const TransformationContext& transformation_context) const override; 55 56 // A transformation that inserts a conditional statement with a boolean 57 // expression of arbitrary value and duplicates a given single-entry, 58 // single-exit region, so that it is present in each conditional branch and 59 // will be executed regardless of which branch will be taken. 60 void Apply(opt::IRContext* ir_context, 61 TransformationContext* transformation_context) const override; 62 63 // Returns the set of blocks dominated by |entry_block| and post-dominated 64 // by |exit_block|. 65 static std::set<opt::BasicBlock*> GetRegionBlocks( 66 opt::IRContext* ir_context, opt::BasicBlock* entry_block, 67 opt::BasicBlock* exit_block); 68 69 // Returns true if and only if |instr| is available at the end of the region 70 // for which |exit_block| is the final block. 71 static bool AvailableAfterRegion(const opt::Instruction& instr, 72 opt::BasicBlock* exit_block, 73 opt::IRContext* ir_context); 74 75 // Returns true if and only if |instr| is valid as an argument to an OpPhi 76 // instruction. 77 static bool ValidOpPhiArgument(const opt::Instruction& instr, 78 opt::IRContext* ir_context); 79 80 std::unordered_set<uint32_t> GetFreshIds() const override; 81 82 protobufs::Transformation ToMessage() const override; 83 84 private: 85 protobufs::TransformationDuplicateRegionWithSelection message_; 86 }; 87 88 } // namespace fuzz 89 } // namespace spvtools 90 91 #endif // SOURCE_FUZZ_TRANSFORMATION_DUPLICATE_REGION_WITH_SELECTION_H_ 92