| 1583 | } |
| 1584 | |
| 1585 | bool IdUseCanBeReplaced(opt::IRContext* ir_context, |
| 1586 | const TransformationContext& transformation_context, |
| 1587 | opt::Instruction* use_instruction, |
| 1588 | uint32_t use_in_operand_index) { |
| 1589 | if (spvOpcodeIsAccessChain(use_instruction->opcode()) && |
| 1590 | use_in_operand_index > 0) { |
| 1591 | // A replacement for an irrelevant index in OpAccessChain must be clamped |
| 1592 | // first. |
| 1593 | if (transformation_context.GetFactManager()->IdIsIrrelevant( |
| 1594 | use_instruction->GetSingleWordInOperand(use_in_operand_index))) { |
| 1595 | return false; |
| 1596 | } |
| 1597 | |
| 1598 | // This is an access chain index. If the (sub-)object being accessed by the |
| 1599 | // given index has struct type then we cannot replace the use, as it needs |
| 1600 | // to be an OpConstant. |
| 1601 | |
| 1602 | // Get the top-level composite type that is being accessed. |
| 1603 | auto object_being_accessed = ir_context->get_def_use_mgr()->GetDef( |
| 1604 | use_instruction->GetSingleWordInOperand(0)); |
| 1605 | auto pointer_type = |
| 1606 | ir_context->get_type_mgr()->GetType(object_being_accessed->type_id()); |
| 1607 | assert(pointer_type->AsPointer()); |
| 1608 | auto composite_type_being_accessed = |
| 1609 | pointer_type->AsPointer()->pointee_type(); |
| 1610 | |
| 1611 | // Now walk the access chain, tracking the type of each sub-object of the |
| 1612 | // composite that is traversed, until the index of interest is reached. |
| 1613 | for (uint32_t index_in_operand = 1; index_in_operand < use_in_operand_index; |
| 1614 | index_in_operand++) { |
| 1615 | // For vectors, matrices and arrays, getting the type of the sub-object is |
| 1616 | // trivial. For the struct case, the sub-object type is field-sensitive, |
| 1617 | // and depends on the constant index that is used. |
| 1618 | if (composite_type_being_accessed->AsVector()) { |
| 1619 | composite_type_being_accessed = |
| 1620 | composite_type_being_accessed->AsVector()->element_type(); |
| 1621 | } else if (composite_type_being_accessed->AsMatrix()) { |
| 1622 | composite_type_being_accessed = |
| 1623 | composite_type_being_accessed->AsMatrix()->element_type(); |
| 1624 | } else if (composite_type_being_accessed->AsArray()) { |
| 1625 | composite_type_being_accessed = |
| 1626 | composite_type_being_accessed->AsArray()->element_type(); |
| 1627 | } else if (composite_type_being_accessed->AsRuntimeArray()) { |
| 1628 | composite_type_being_accessed = |
| 1629 | composite_type_being_accessed->AsRuntimeArray()->element_type(); |
| 1630 | } else { |
| 1631 | assert(composite_type_being_accessed->AsStruct()); |
| 1632 | auto constant_index_instruction = ir_context->get_def_use_mgr()->GetDef( |
| 1633 | use_instruction->GetSingleWordInOperand(index_in_operand)); |
| 1634 | assert(constant_index_instruction->opcode() == spv::Op::OpConstant); |
| 1635 | uint32_t member_index = |
| 1636 | constant_index_instruction->GetSingleWordInOperand(0); |
| 1637 | composite_type_being_accessed = |
| 1638 | composite_type_being_accessed->AsStruct() |
| 1639 | ->element_types()[member_index]; |
| 1640 | } |
| 1641 | } |
| 1642 |
no test coverage detected