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 | IRContext::kAnalysisConstants | 36 IRContext::kAnalysisTypes; 37 } 38 39 private: 40 // Returns true if |id| is a valid type for use with OpSelect. OpSelect only 41 // allows scalars, vectors and pointers as valid inputs. 42 bool CheckType(uint32_t id); 43 44 // Returns the basic block containing |id|. 45 BasicBlock* GetBlock(uint32_t id); 46 47 // Returns the basic block for the |predecessor|'th index predecessor of 48 // |phi|. 49 BasicBlock* GetIncomingBlock(Instruction* phi, uint32_t predecessor); 50 51 // Returns the instruction defining the |predecessor|'th index of |phi|. 52 Instruction* GetIncomingValue(Instruction* phi, uint32_t predecessor); 53 54 // Returns the id of a OpCompositeConstruct boolean vector. The composite has 55 // the same number of elements as |vec_data_ty| and each member is |cond|. 56 // |where| indicates the location in |block| to insert the composite 57 // construct. If necessary, this function will also construct the necessary 58 // type instructions for the boolean vector. 59 uint32_t SplatCondition(analysis::Vector* vec_data_ty, uint32_t cond, 60 InstructionBuilder* builder); 61 62 // Returns true if none of |phi|'s users are in |block|. 63 bool CheckPhiUsers(Instruction* phi, BasicBlock* block); 64 65 // Returns |false| if |block| is not appropriate to transform. Only 66 // transforms blocks with two predecessors. Neither incoming block can be 67 // dominated by |block|. Both predecessors must share a common dominator that 68 // is terminated by a conditional branch. 69 bool CheckBlock(BasicBlock* block, DominatorAnalysis* dominators, 70 BasicBlock** common); 71 72 // Moves |inst| to |target_block| if it does not already dominate the block. 73 // Any instructions that |inst| depends on are move if necessary. It is 74 // assumed that |inst| can be hoisted to |target_block| as defined by 75 // |CanHoistInstruction|. |dominators| is the dominator analysis for the 76 // function that contains |target_block|. 77 void HoistInstruction(Instruction* inst, BasicBlock* target_block, 78 DominatorAnalysis* dominators); 79 80 // Returns true if it is legal to move |inst| and the instructions it depends 81 // on to |target_block| if they do not already dominate |target_block|. 82 bool CanHoistInstruction(Instruction* inst, BasicBlock* target_block, 83 DominatorAnalysis* dominators); 84 }; 85 86 } // namespace opt 87 } // namespace spvtools 88 89 #endif // SOURCE_OPT_IF_CONVERSION_H_ 90