If the input to an OpCompositeExtract is an OpLoad, we can change the load into a load of an OpAccessChain.
| 2241 | // If the input to an OpCompositeExtract is an OpLoad, we can change the |
| 2242 | // load into a load of an OpAccessChain. |
| 2243 | bool LoadFeedingExtract(IRContext* context, Instruction* inst, |
| 2244 | const std::vector<const analysis::Constant*>&) { |
| 2245 | assert(inst->opcode() == spv::Op::OpCompositeExtract && |
| 2246 | "Wrong opcode. Should be OpCompositeExtract."); |
| 2247 | |
| 2248 | analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); |
| 2249 | uint32_t cid = inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); |
| 2250 | Instruction* cinst = def_use_mgr->GetDef(cid); |
| 2251 | |
| 2252 | if (cinst->opcode() != spv::Op::OpLoad) { |
| 2253 | return false; |
| 2254 | } |
| 2255 | |
| 2256 | Instruction* composite_type_inst = def_use_mgr->GetDef(cinst->type_id()); |
| 2257 | if (composite_type_inst->opcode() != spv::Op::OpTypeStruct && |
| 2258 | composite_type_inst->opcode() != spv::Op::OpTypeArray) { |
| 2259 | return false; |
| 2260 | } |
| 2261 | |
| 2262 | // Check the memory operands. |
| 2263 | if (cinst->NumInOperands() > 1) { |
| 2264 | uint32_t memory_access_mask = cinst->GetSingleWordInOperand(1); |
| 2265 | if (memory_access_mask & uint32_t(spv::MemoryAccessMask::Volatile)) { |
| 2266 | return false; |
| 2267 | } |
| 2268 | } |
| 2269 | |
| 2270 | uint32_t ptr_id = cinst->GetSingleWordInOperand(0); |
| 2271 | Instruction* ptr_inst = def_use_mgr->GetDef(ptr_id); |
| 2272 | Instruction* ptr_type_inst = def_use_mgr->GetDef(ptr_inst->type_id()); |
| 2273 | assert(ptr_type_inst->opcode() == spv::Op::OpTypePointer); |
| 2274 | spv::StorageClass storage_class = |
| 2275 | static_cast<spv::StorageClass>(ptr_type_inst->GetSingleWordInOperand(0)); |
| 2276 | |
| 2277 | // If the storage class is Function or Private, we do not want to fold. |
| 2278 | // These are the storage classes that the local-access-chain-convert pass |
| 2279 | // works on. |
| 2280 | if (storage_class == spv::StorageClass::Function || |
| 2281 | storage_class == spv::StorageClass::Private) { |
| 2282 | return false; |
| 2283 | } |
| 2284 | |
| 2285 | analysis::ConstantManager* const_mgr = context->get_constant_mgr(); |
| 2286 | analysis::TypeManager* type_mgr = context->get_type_mgr(); |
| 2287 | std::vector<uint32_t> index_ids; |
| 2288 | for (uint32_t i = 1; i < inst->NumInOperands(); ++i) { |
| 2289 | uint32_t index = inst->GetSingleWordInOperand(i); |
| 2290 | const analysis::Constant* index_const = |
| 2291 | const_mgr->GetConstant(type_mgr->GetUIntType(), {index}); |
| 2292 | index_ids.push_back( |
| 2293 | const_mgr->GetDefiningInstruction(index_const)->result_id()); |
| 2294 | } |
| 2295 | |
| 2296 | InstructionBuilder ir_builder( |
| 2297 | context, cinst, |
| 2298 | IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); |
| 2299 | |
| 2300 | uint32_t element_ptr_type_id = |
nothing calls this directly
no test coverage detected