1 // Copyright (c) 2018 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_OPT_IF_CONVERSION_H_ 16 #define SOURCE_OPT_IF_CONVERSION_H_ 17 18 #include "source/opt/basic_block.h" 19 #include "source/opt/ir_builder.h" 20 #include "source/opt/pass.h" 21 #include "source/opt/types.h" 22 23 namespace spvtools { 24 namespace opt { 25 26 // See optimizer.hpp for documentation. 27 class IfConversion : public Pass { 28 public: name()29 const char* name() const override { return "if-conversion"; } 30 Status Process() override; 31 GetPreservedAnalyses()32 IRContext::Analysis GetPreservedAnalyses() override { 33 return IRContext::kAnalysisDefUse | IRContext::kAnalysisDominatorAnalysis | 34 IRContext::kAnalysisInstrToBlockMapping | IRContext::kAnalysisCFG | 35 IRContext::kAnalysisNameMap; 36 } 37 38 private: 39 // Returns true if |id| is a valid type for use with OpSelect. OpSelect only 40 // allows scalars, vectors and pointers as valid inputs. 41 bool CheckType(uint32_t id); 42 43 // Returns the basic block containing |id|. 44 BasicBlock* GetBlock(uint32_t id); 45 46 // Returns the basic block for the |predecessor|'th index predecessor of 47 // |phi|. 48 BasicBlock* GetIncomingBlock(Instruction* phi, uint32_t predecessor); 49 50 // Returns the instruction defining the |predecessor|'th index of |phi|. 51 Instruction* GetIncomingValue(Instruction* phi, uint32_t predecessor); 52 53 // Returns the id of a OpCompositeConstruct boolean vector. The composite has 54 // the same number of elements as |vec_data_ty| and each member is |cond|. 55 // |where| indicates the location in |block| to insert the composite 56 // construct. If necessary, this function will also construct the necessary 57 // type instructions for the boolean vector. 58 uint32_t SplatCondition(analysis::Vector* vec_data_ty, uint32_t cond, 59 InstructionBuilder* builder); 60 61 // Returns true if none of |phi|'s users are in |block|. 62 bool CheckPhiUsers(Instruction* phi, BasicBlock* block); 63 64 // Returns |false| if |block| is not appropriate to transform. Only 65 // transforms blocks with two predecessors. Neither incoming block can be 66 // dominated by |block|. Both predecessors must share a common dominator that 67 // is terminated by a conditional branch. 68 bool CheckBlock(BasicBlock* block, DominatorAnalysis* dominators, 69 BasicBlock** common); 70 71 // Moves |inst| to |target_block| if it does not already dominate the block. 72 // Any instructions that |inst| depends on are move if necessary. It is 73 // assumed that |inst| can be hoisted to |target_block| as defined by 74 // |CanHoistInstruction|. |dominators| is the dominator analysis for the 75 // function that contains |target_block|. 76 void HoistInstruction(Instruction* inst, BasicBlock* target_block, 77 DominatorAnalysis* dominators); 78 79 // Returns true if it is legal to move |inst| and the instructions it depends 80 // on to |target_block| if they do not already dominate |target_block|. 81 bool CanHoistInstruction(Instruction* inst, BasicBlock* target_block, 82 DominatorAnalysis* dominators); 83 }; 84 85 } // namespace opt 86 } // namespace spvtools 87 88 #endif // SOURCE_OPT_IF_CONVERSION_H_ 89