1 // Copyright (c) 2017 The Khronos Group Inc. 2 // Copyright (c) 2017 Valve Corporation 3 // Copyright (c) 2017 LunarG Inc. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 #ifndef SOURCE_OPT_LOCAL_ACCESS_CHAIN_CONVERT_PASS_H_ 18 #define SOURCE_OPT_LOCAL_ACCESS_CHAIN_CONVERT_PASS_H_ 19 20 #include <algorithm> 21 #include <map> 22 #include <memory> 23 #include <queue> 24 #include <string> 25 #include <unordered_map> 26 #include <unordered_set> 27 #include <utility> 28 #include <vector> 29 30 #include "source/opt/basic_block.h" 31 #include "source/opt/def_use_manager.h" 32 #include "source/opt/mem_pass.h" 33 #include "source/opt/module.h" 34 35 namespace spvtools { 36 namespace opt { 37 38 // See optimizer.hpp for documentation. 39 class LocalAccessChainConvertPass : public MemPass { 40 public: 41 LocalAccessChainConvertPass(); 42 name()43 const char* name() const override { return "convert-local-access-chains"; } 44 Status Process() override; 45 GetPreservedAnalyses()46 IRContext::Analysis GetPreservedAnalyses() override { 47 return IRContext::kAnalysisDefUse; 48 } 49 50 using ProcessFunction = std::function<bool(Function*)>; 51 52 private: 53 // Return true if all refs through |ptrId| are only loads or stores and 54 // cache ptrId in supported_ref_ptrs_. TODO(dnovillo): This function is 55 // replicated in other passes and it's slightly different in every pass. Is it 56 // possible to make one common implementation? 57 bool HasOnlySupportedRefs(uint32_t ptrId); 58 59 // Search |func| and cache function scope variables of target type that are 60 // not accessed with non-constant-index access chains. Also cache non-target 61 // variables. 62 void FindTargetVars(Function* func); 63 64 // Build instruction from |opcode|, |typeId|, |resultId|, and |in_opnds|. 65 // Append to |newInsts|. 66 void BuildAndAppendInst(SpvOp opcode, uint32_t typeId, uint32_t resultId, 67 const std::vector<Operand>& in_opnds, 68 std::vector<std::unique_ptr<Instruction>>* newInsts); 69 70 // Build load of variable in |ptrInst| and append to |newInsts|. 71 // Return var in |varId| and its pointee type in |varPteTypeId|. 72 uint32_t BuildAndAppendVarLoad( 73 const Instruction* ptrInst, uint32_t* varId, uint32_t* varPteTypeId, 74 std::vector<std::unique_ptr<Instruction>>* newInsts); 75 76 // Append literal integer operands to |in_opnds| corresponding to constant 77 // integer operands from access chain |ptrInst|. Assumes all indices in 78 // access chains are OpConstant. 79 void AppendConstantOperands(const Instruction* ptrInst, 80 std::vector<Operand>* in_opnds); 81 82 // Create a load/insert/store equivalent to a store of 83 // |valId| through (constant index) access chaing |ptrInst|. 84 // Append to |newInsts|. 85 void GenAccessChainStoreReplacement( 86 const Instruction* ptrInst, uint32_t valId, 87 std::vector<std::unique_ptr<Instruction>>* newInsts); 88 89 // For the (constant index) access chain |address_inst|, create an 90 // equivalent load and extract that replaces |original_load|. The result id 91 // of the extract will be the same as the original result id of 92 // |original_load|. 93 void ReplaceAccessChainLoad(const Instruction* address_inst, 94 Instruction* original_load); 95 96 // Return true if all indices of access chain |acp| are OpConstant integers 97 bool IsConstantIndexAccessChain(const Instruction* acp) const; 98 99 // Identify all function scope variables of target type which are 100 // accessed only with loads, stores and access chains with constant 101 // indices. Convert all loads and stores of such variables into equivalent 102 // loads, stores, extracts and inserts. This unifies access to these 103 // variables to a single mode and simplifies analysis and optimization. 104 // See IsTargetType() for targeted types. 105 // 106 // Nested access chains and pointer access chains are not currently 107 // converted. 108 bool ConvertLocalAccessChains(Function* func); 109 110 // Initialize extensions whitelist 111 void InitExtensions(); 112 113 // Return true if all extensions in this module are allowed by this pass. 114 bool AllExtensionsSupported() const; 115 116 void Initialize(); 117 Pass::Status ProcessImpl(); 118 119 // Variables with only supported references, ie. loads and stores using 120 // variable directly or through non-ptr access chains. 121 std::unordered_set<uint32_t> supported_ref_ptrs_; 122 123 // Extensions supported by this pass. 124 std::unordered_set<std::string> extensions_whitelist_; 125 }; 126 127 } // namespace opt 128 } // namespace spvtools 129 130 #endif // SOURCE_OPT_LOCAL_ACCESS_CHAIN_CONVERT_PASS_H_ 131