If the OpCompositeConstruct is simply putting back together elements that where extracted from the same source, we can simply reuse the source. This is a common code pattern because of the way that scalar replacement works.
| 2394 | // This is a common code pattern because of the way that scalar replacement |
| 2395 | // works. |
| 2396 | bool CompositeExtractFeedingConstruct( |
| 2397 | IRContext* context, Instruction* inst, |
| 2398 | const std::vector<const analysis::Constant*>&) { |
| 2399 | assert(inst->opcode() == spv::Op::OpCompositeConstruct && |
| 2400 | "Wrong opcode. Should be OpCompositeConstruct."); |
| 2401 | analysis::DefUseManager* def_use_mgr = context->get_def_use_mgr(); |
| 2402 | uint32_t original_id = 0; |
| 2403 | |
| 2404 | if (inst->NumInOperands() == 0) { |
| 2405 | // The struct being constructed has no members. |
| 2406 | return false; |
| 2407 | } |
| 2408 | |
| 2409 | // Check each element to make sure they are: |
| 2410 | // - extractions |
| 2411 | // - extracting the same position they are inserting |
| 2412 | // - all extract from the same id. |
| 2413 | Instruction* first_element_inst = nullptr; |
| 2414 | for (uint32_t i = 0; i < inst->NumInOperands(); ++i) { |
| 2415 | const uint32_t element_id = inst->GetSingleWordInOperand(i); |
| 2416 | Instruction* element_inst = def_use_mgr->GetDef(element_id); |
| 2417 | if (first_element_inst == nullptr) { |
| 2418 | first_element_inst = element_inst; |
| 2419 | } |
| 2420 | |
| 2421 | if (element_inst->opcode() != spv::Op::OpCompositeExtract) { |
| 2422 | return false; |
| 2423 | } |
| 2424 | |
| 2425 | if (!HaveSameIndexesExceptForLast(element_inst, first_element_inst)) { |
| 2426 | return false; |
| 2427 | } |
| 2428 | |
| 2429 | if (element_inst->GetSingleWordInOperand(element_inst->NumInOperands() - |
| 2430 | 1) != i) { |
| 2431 | return false; |
| 2432 | } |
| 2433 | |
| 2434 | if (i == 0) { |
| 2435 | original_id = |
| 2436 | element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx); |
| 2437 | } else if (original_id != |
| 2438 | element_inst->GetSingleWordInOperand(kExtractCompositeIdInIdx)) { |
| 2439 | return false; |
| 2440 | } |
| 2441 | } |
| 2442 | assert(first_element_inst != nullptr); |
| 2443 | |
| 2444 | // The last check it to see that the object being extracted from is the |
| 2445 | // correct type. |
| 2446 | Instruction* original_inst = def_use_mgr->GetDef(original_id); |
| 2447 | uint32_t original_type_id = |
| 2448 | GetElementType(original_inst->type_id(), first_element_inst->begin() + 3, |
| 2449 | first_element_inst->end() - 1, def_use_mgr); |
| 2450 | |
| 2451 | if (inst->type_id() != original_type_id) { |
| 2452 | return false; |
| 2453 | } |
nothing calls this directly
no test coverage detected