diff options
Diffstat (limited to '3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp')
-rw-r--r-- | 3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp | 516 |
1 files changed, 278 insertions, 238 deletions
diff --git a/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp b/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp index 028b237d73e..0b235629bfd 100644 --- a/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp +++ b/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp @@ -26,12 +26,24 @@ const uint32_t kLoadPointerInOperand = 0; const uint32_t kStorePointerInOperand = 0; const uint32_t kStoreObjectInOperand = 1; const uint32_t kCompositeExtractObjectInOperand = 0; +const uint32_t kTypePointerStorageClassInIdx = 0; +const uint32_t kTypePointerPointeeInIdx = 1; + +bool IsDebugDeclareOrValue(Instruction* di) { + auto dbg_opcode = di->GetCommonDebugOpcode(); + return dbg_opcode == CommonDebugInfoDebugDeclare || + dbg_opcode == CommonDebugInfoDebugValue; +} } // namespace Pass::Status CopyPropagateArrays::Process() { bool modified = false; for (Function& function : *get_module()) { + if (function.IsDeclaration()) { + continue; + } + BasicBlock* entry_bb = &*function.begin(); for (auto var_inst = entry_bb->begin(); var_inst->opcode() == SpvOpVariable; @@ -51,7 +63,7 @@ Pass::Status CopyPropagateArrays::Process() { FindSourceObjectIfPossible(&*var_inst, store_inst); if (source_object != nullptr) { - if (CanUpdateUses(&*var_inst, source_object->GetPointerTypeId())) { + if (CanUpdateUses(&*var_inst, source_object->GetPointerTypeId(this))) { modified = true; PropagateObject(&*var_inst, source_object.get(), store_inst); } @@ -139,9 +151,17 @@ Instruction* CopyPropagateArrays::BuildNewAccessChain( return source->GetVariable(); } - return builder.AddAccessChain(source->GetPointerTypeId(), - source->GetVariable()->result_id(), - source->AccessChain()); + source->BuildConstants(); + std::vector<uint32_t> access_ids(source->AccessChain().size()); + std::transform( + source->AccessChain().cbegin(), source->AccessChain().cend(), + access_ids.begin(), [](const AccessChainEntry& entry) { + assert(entry.is_result_id && "Constants needs to be built first."); + return entry.result_id; + }); + + return builder.AddAccessChain(source->GetPointerTypeId(this), + source->GetVariable()->result_id(), access_ids); } bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) { @@ -156,6 +176,8 @@ bool CopyPropagateArrays::HasNoStores(Instruction* ptr_inst) { return false; } else if (use->opcode() == SpvOpImageTexelPointer) { return true; + } else if (use->opcode() == SpvOpEntryPoint) { + return true; } // Some other instruction. Be conservative. return false; @@ -186,6 +208,8 @@ bool CopyPropagateArrays::HasValidReferencesOnly(Instruction* ptr_inst, return ptr_inst->opcode() == SpvOpVariable && store_inst->GetSingleWordInOperand(kStorePointerInOperand) == ptr_inst->result_id(); + } else if (IsDebugDeclareOrValue(use)) { + return true; } // Some other instruction. Be conservative. return false; @@ -254,30 +278,20 @@ std::unique_ptr<CopyPropagateArrays::MemoryObject> CopyPropagateArrays::BuildMemoryObjectFromExtract(Instruction* extract_inst) { assert(extract_inst->opcode() == SpvOpCompositeExtract && "Expecting an OpCompositeExtract instruction."); - analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); - std::unique_ptr<MemoryObject> result = GetSourceObjectIfAny( extract_inst->GetSingleWordInOperand(kCompositeExtractObjectInOperand)); - if (result) { - analysis::Integer int_type(32, false); - const analysis::Type* uint32_type = - context()->get_type_mgr()->GetRegisteredType(&int_type); - - std::vector<uint32_t> components; - // Convert the indices in the extract instruction to a series of ids that - // can be used by the |OpAccessChain| instruction. - for (uint32_t i = 1; i < extract_inst->NumInOperands(); ++i) { - uint32_t index = extract_inst->GetSingleWordInOperand(i); - const analysis::Constant* index_const = - const_mgr->GetConstant(uint32_type, {index}); - components.push_back( - const_mgr->GetDefiningInstruction(index_const)->result_id()); - } - result->GetMember(components); - return result; + if (!result) { + return nullptr; } - return nullptr; + + // Copy the indices of the extract instruction to |OpAccessChain| indices. + std::vector<AccessChainEntry> components; + for (uint32_t i = 1; i < extract_inst->NumInOperands(); ++i) { + components.push_back({false, {extract_inst->GetSingleWordInOperand(i)}}); + } + result->PushIndirection(components); + return result; } std::unique_ptr<CopyPropagateArrays::MemoryObject> @@ -301,20 +315,12 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct( return nullptr; } - analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); - const analysis::Constant* last_access = - const_mgr->FindDeclaredConstant(memory_object->AccessChain().back()); - if (!last_access || - (!last_access->AsIntConstant() && !last_access->AsNullConstant())) { - return nullptr; - } - - if (last_access->GetU32() != 0) { + AccessChainEntry last_access = memory_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(last_access, 0)) { return nullptr; } - memory_object->GetParent(); - + memory_object->PopIndirection(); if (memory_object->GetNumberOfMembers() != conststruct_inst->NumInOperands()) { return nullptr; @@ -324,21 +330,20 @@ CopyPropagateArrays::BuildMemoryObjectFromCompositeConstruct( std::unique_ptr<MemoryObject> member_object = GetSourceObjectIfAny(conststruct_inst->GetSingleWordInOperand(i)); - if (!member_object->IsMember()) { + if (!member_object) { return nullptr; } - if (!memory_object->Contains(member_object.get())) { + if (!member_object->IsMember()) { return nullptr; } - last_access = - const_mgr->FindDeclaredConstant(member_object->AccessChain().back()); - if (!last_access || !last_access->AsIntConstant()) { + if (!memory_object->Contains(member_object.get())) { return nullptr; } - if (last_access->GetU32() != i) { + last_access = member_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(last_access, i)) { return nullptr; } } @@ -362,8 +367,7 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { } else if (const analysis::Array* array_type = result_type->AsArray()) { const analysis::Constant* length_const = const_mgr->FindDeclaredConstant(array_type->LengthId()); - assert(length_const->AsIntConstant()); - number_of_elements = length_const->AsIntConstant()->GetU32(); + number_of_elements = length_const->GetU32(); } else if (const analysis::Vector* vector_type = result_type->AsVector()) { number_of_elements = vector_type->element_count(); } else if (const analysis::Matrix* matrix_type = result_type->AsMatrix()) { @@ -393,17 +397,12 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { return nullptr; } - const analysis::Constant* last_access = - const_mgr->FindDeclaredConstant(memory_object->AccessChain().back()); - if (!last_access || !last_access->AsIntConstant()) { - return nullptr; - } - - if (last_access->GetU32() != number_of_elements - 1) { + AccessChainEntry last_access = memory_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(last_access, number_of_elements - 1)) { return nullptr; } - memory_object->GetParent(); + memory_object->PopIndirection(); Instruction* current_insert = def_use_mgr->GetDef(insert_inst->GetSingleWordInOperand(1)); @@ -440,14 +439,9 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { return nullptr; } - const analysis::Constant* current_last_access = - const_mgr->FindDeclaredConstant( - current_memory_object->AccessChain().back()); - if (!current_last_access || !current_last_access->AsIntConstant()) { - return nullptr; - } - - if (current_last_access->GetU32() != i - 1) { + AccessChainEntry current_last_access = + current_memory_object->AccessChain().back(); + if (!IsAccessChainIndexValidAndEqualTo(current_last_access, i - 1)) { return nullptr; } current_insert = @@ -457,6 +451,21 @@ CopyPropagateArrays::BuildMemoryObjectFromInsert(Instruction* insert_inst) { return memory_object; } +bool CopyPropagateArrays::IsAccessChainIndexValidAndEqualTo( + const AccessChainEntry& entry, uint32_t value) const { + if (!entry.is_result_id) { + return entry.immediate == value; + } + + analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); + const analysis::Constant* constant = + const_mgr->FindDeclaredConstant(entry.result_id); + if (!constant || !constant->type()->AsInteger()) { + return false; + } + return constant->GetU32() == value; +} + bool CopyPropagateArrays::IsPointerToArrayType(uint32_t type_id) { analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::Pointer* pointer_type = type_mgr->GetType(type_id)->AsPointer(); @@ -484,88 +493,94 @@ bool CopyPropagateArrays::CanUpdateUses(Instruction* original_ptr_inst, return true; } - return def_use_mgr->WhileEachUse( - original_ptr_inst, - [this, type_mgr, const_mgr, type](Instruction* use, uint32_t) { - switch (use->opcode()) { - case SpvOpLoad: { - analysis::Pointer* pointer_type = type->AsPointer(); - uint32_t new_type_id = - type_mgr->GetId(pointer_type->pointee_type()); + return def_use_mgr->WhileEachUse(original_ptr_inst, [this, type_mgr, + const_mgr, + type](Instruction* use, + uint32_t) { + if (IsDebugDeclareOrValue(use)) return true; - if (new_type_id != use->type_id()) { - return CanUpdateUses(use, new_type_id); - } - return true; - } - case SpvOpAccessChain: { - analysis::Pointer* pointer_type = type->AsPointer(); - const analysis::Type* pointee_type = pointer_type->pointee_type(); - - std::vector<uint32_t> access_chain; - for (uint32_t i = 1; i < use->NumInOperands(); ++i) { - const analysis::Constant* index_const = - const_mgr->FindDeclaredConstant( - use->GetSingleWordInOperand(i)); - if (index_const) { - access_chain.push_back(index_const->AsIntConstant()->GetU32()); - } else { - // Variable index means the type is a type where every element - // is the same type. Use element 0 to get the type. - access_chain.push_back(0); - } - } + switch (use->opcode()) { + case SpvOpLoad: { + analysis::Pointer* pointer_type = type->AsPointer(); + uint32_t new_type_id = type_mgr->GetId(pointer_type->pointee_type()); + + if (new_type_id != use->type_id()) { + return CanUpdateUses(use, new_type_id); + } + return true; + } + case SpvOpAccessChain: { + analysis::Pointer* pointer_type = type->AsPointer(); + const analysis::Type* pointee_type = pointer_type->pointee_type(); - const analysis::Type* new_pointee_type = - type_mgr->GetMemberType(pointee_type, access_chain); - analysis::Pointer pointerTy(new_pointee_type, - pointer_type->storage_class()); - uint32_t new_pointer_type_id = - context()->get_type_mgr()->GetTypeInstruction(&pointerTy); + std::vector<uint32_t> access_chain; + for (uint32_t i = 1; i < use->NumInOperands(); ++i) { + const analysis::Constant* index_const = + const_mgr->FindDeclaredConstant(use->GetSingleWordInOperand(i)); + if (index_const) { + access_chain.push_back(index_const->GetU32()); + } else { + // Variable index means the type is a type where every element + // is the same type. Use element 0 to get the type. + access_chain.push_back(0); - if (new_pointer_type_id != use->type_id()) { - return CanUpdateUses(use, new_pointer_type_id); + // We are trying to access a struct with variable indices. + // This cannot happen. + if (pointee_type->kind() == analysis::Type::kStruct) { + return false; } - return true; } - case SpvOpCompositeExtract: { - std::vector<uint32_t> access_chain; - for (uint32_t i = 1; i < use->NumInOperands(); ++i) { - access_chain.push_back(use->GetSingleWordInOperand(i)); - } + } - const analysis::Type* new_type = - type_mgr->GetMemberType(type, access_chain); - uint32_t new_type_id = type_mgr->GetTypeInstruction(new_type); + const analysis::Type* new_pointee_type = + type_mgr->GetMemberType(pointee_type, access_chain); + analysis::Pointer pointerTy(new_pointee_type, + pointer_type->storage_class()); + uint32_t new_pointer_type_id = + context()->get_type_mgr()->GetTypeInstruction(&pointerTy); + if (new_pointer_type_id == 0) { + return false; + } - if (new_type_id != use->type_id()) { - return CanUpdateUses(use, new_type_id); - } - return true; - } - case SpvOpStore: - // Can't handle changing the type of a store. There are too many - // other things that might need to change as well. Not worth the - // effort. Punting for now. - - // TODO (s-perron): This can be handled by expanding the store into - // a series of extracts, composite constructs, and a store. - return true; - case SpvOpImageTexelPointer: - case SpvOpName: - return true; - default: - return use->IsDecoration(); + if (new_pointer_type_id != use->type_id()) { + return CanUpdateUses(use, new_pointer_type_id); } - }); + return true; + } + case SpvOpCompositeExtract: { + std::vector<uint32_t> access_chain; + for (uint32_t i = 1; i < use->NumInOperands(); ++i) { + access_chain.push_back(use->GetSingleWordInOperand(i)); + } + + const analysis::Type* new_type = + type_mgr->GetMemberType(type, access_chain); + uint32_t new_type_id = type_mgr->GetTypeInstruction(new_type); + if (new_type_id == 0) { + return false; + } + + if (new_type_id != use->type_id()) { + return CanUpdateUses(use, new_type_id); + } + return true; + } + case SpvOpStore: + // If needed, we can create an element-by-element copy to change the + // type of the value being stored. This way we can always handled + // stores. + return true; + case SpvOpImageTexelPointer: + case SpvOpName: + return true; + default: + return use->IsDecoration(); + } + }); } + void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, Instruction* new_ptr_inst) { - // TODO (s-perron): Keep the def-use manager up to date. Not done now because - // it can cause problems for the |ForEachUse| traversals. Can be use by - // keeping a list of instructions that need updating, and then updating them - // in |PropagateObject|. - analysis::TypeManager* type_mgr = context()->get_type_mgr(); analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); analysis::DefUseManager* def_use_mgr = context()->get_def_use_mgr(); @@ -579,7 +594,51 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, for (auto pair : uses) { Instruction* use = pair.first; uint32_t index = pair.second; - analysis::Pointer* pointer_type = nullptr; + + if (use->IsCommonDebugInstr()) { + switch (use->GetCommonDebugOpcode()) { + case CommonDebugInfoDebugDeclare: { + if (new_ptr_inst->opcode() == SpvOpVariable || + new_ptr_inst->opcode() == SpvOpFunctionParameter) { + context()->ForgetUses(use); + use->SetOperand(index, {new_ptr_inst->result_id()}); + context()->AnalyzeUses(use); + } else { + // Based on the spec, we cannot use a pointer other than OpVariable + // or OpFunctionParameter for DebugDeclare. We have to use + // DebugValue with Deref. + + context()->ForgetUses(use); + + // Change DebugDeclare to DebugValue. + use->SetOperand(index - 2, + {static_cast<uint32_t>(CommonDebugInfoDebugValue)}); + use->SetOperand(index, {new_ptr_inst->result_id()}); + + // Add Deref operation. + Instruction* dbg_expr = + def_use_mgr->GetDef(use->GetSingleWordOperand(index + 1)); + auto* deref_expr_instr = + context()->get_debug_info_mgr()->DerefDebugExpression(dbg_expr); + use->SetOperand(index + 1, {deref_expr_instr->result_id()}); + + context()->AnalyzeUses(deref_expr_instr); + context()->AnalyzeUses(use); + } + break; + } + case CommonDebugInfoDebugValue: + context()->ForgetUses(use); + use->SetOperand(index, {new_ptr_inst->result_id()}); + context()->AnalyzeUses(use); + break; + default: + assert(false && "Don't know how to rewrite instruction"); + break; + } + continue; + } + switch (use->opcode()) { case SpvOpLoad: { // Replace the actual use. @@ -587,8 +646,10 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, use->SetOperand(index, {new_ptr_inst->result_id()}); // Update the type. - pointer_type = type_mgr->GetType(new_ptr_inst->type_id())->AsPointer(); - uint32_t new_type_id = type_mgr->GetId(pointer_type->pointee_type()); + Instruction* pointer_type_inst = + def_use_mgr->GetDef(new_ptr_inst->type_id()); + uint32_t new_type_id = + pointer_type_inst->GetSingleWordInOperand(kTypePointerPointeeInIdx); if (new_type_id != use->type_id()) { use->SetResultType(new_type_id); context()->AnalyzeUses(use); @@ -602,10 +663,6 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, context()->ForgetUses(use); use->SetOperand(index, {new_ptr_inst->result_id()}); - // Update the result type. - pointer_type = type_mgr->GetType(new_ptr_inst->type_id())->AsPointer(); - const analysis::Type* pointee_type = pointer_type->pointee_type(); - // Convert the ids on the OpAccessChain to indices that can be used to // get the specific member. std::vector<uint32_t> access_chain; @@ -613,21 +670,27 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, const analysis::Constant* index_const = const_mgr->FindDeclaredConstant(use->GetSingleWordInOperand(i)); if (index_const) { - access_chain.push_back(index_const->AsIntConstant()->GetU32()); + access_chain.push_back(index_const->GetU32()); } else { // Variable index means the type is an type where every element // is the same type. Use element 0 to get the type. access_chain.push_back(0); } } - const analysis::Type* new_pointee_type = - type_mgr->GetMemberType(pointee_type, access_chain); - // Now build a pointer to the type of the member. - analysis::Pointer new_pointer_type(new_pointee_type, - pointer_type->storage_class()); + Instruction* pointer_type_inst = + get_def_use_mgr()->GetDef(new_ptr_inst->type_id()); + + uint32_t new_pointee_type_id = GetMemberTypeId( + pointer_type_inst->GetSingleWordInOperand(kTypePointerPointeeInIdx), + access_chain); + + SpvStorageClass storage_class = static_cast<SpvStorageClass>( + pointer_type_inst->GetSingleWordInOperand( + kTypePointerStorageClassInIdx)); + uint32_t new_pointer_type_id = - context()->get_type_mgr()->GetTypeInstruction(&new_pointer_type); + type_mgr->FindPointerToType(new_pointee_type_id, storage_class); if (new_pointer_type_id != use->type_id()) { use->SetResultType(new_pointer_type_id); @@ -642,15 +705,13 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, context()->ForgetUses(use); use->SetOperand(index, {new_ptr_inst->result_id()}); + uint32_t new_type_id = new_ptr_inst->type_id(); std::vector<uint32_t> access_chain; for (uint32_t i = 1; i < use->NumInOperands(); ++i) { access_chain.push_back(use->GetSingleWordInOperand(i)); } - const analysis::Type* type = type_mgr->GetType(new_ptr_inst->type_id()); - const analysis::Type* new_type = - type_mgr->GetMemberType(type, access_chain); - uint32_t new_type_id = type_mgr->GetTypeInstruction(new_type); + new_type_id = GetMemberTypeId(new_type_id, access_chain); if (new_type_id != use->type_id()) { use->SetResultType(new_type_id); @@ -672,22 +733,22 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, if (index == 1) { Instruction* target_pointer = def_use_mgr->GetDef( use->GetSingleWordInOperand(kStorePointerInOperand)); - pointer_type = - type_mgr->GetType(target_pointer->type_id())->AsPointer(); - uint32_t copy = - GenerateCopy(original_ptr_inst, - type_mgr->GetId(pointer_type->pointee_type()), use); + Instruction* pointer_type = + def_use_mgr->GetDef(target_pointer->type_id()); + uint32_t pointee_type_id = + pointer_type->GetSingleWordInOperand(kTypePointerPointeeInIdx); + uint32_t copy = GenerateCopy(original_ptr_inst, pointee_type_id, use); context()->ForgetUses(use); use->SetInOperand(index, {copy}); context()->AnalyzeUses(use); } break; + case SpvOpDecorate: + // We treat an OpImageTexelPointer as a load. The result type should + // always have the Image storage class, and should not need to be + // updated. case SpvOpImageTexelPointer: - // We treat an OpImageTexelPointer as a load. The result type should - // always have the Image storage class, and should not need to be - // updated. - // Replace the actual use. context()->ForgetUses(use); use->SetOperand(index, {new_ptr_inst->result_id()}); @@ -700,76 +761,31 @@ void CopyPropagateArrays::UpdateUses(Instruction* original_ptr_inst, } } -uint32_t CopyPropagateArrays::GenerateCopy(Instruction* object_inst, - uint32_t new_type_id, - Instruction* insertion_position) { - analysis::TypeManager* type_mgr = context()->get_type_mgr(); - analysis::ConstantManager* const_mgr = context()->get_constant_mgr(); - - uint32_t original_type_id = object_inst->type_id(); - if (original_type_id == new_type_id) { - return object_inst->result_id(); - } - - InstructionBuilder ir_builder( - context(), insertion_position, - IRContext::kAnalysisInstrToBlockMapping | IRContext::kAnalysisDefUse); - - analysis::Type* original_type = type_mgr->GetType(original_type_id); - analysis::Type* new_type = type_mgr->GetType(new_type_id); - - if (const analysis::Array* original_array_type = original_type->AsArray()) { - uint32_t original_element_type_id = - type_mgr->GetId(original_array_type->element_type()); - - analysis::Array* new_array_type = new_type->AsArray(); - assert(new_array_type != nullptr && "Can't copy an array to a non-array."); - uint32_t new_element_type_id = - type_mgr->GetId(new_array_type->element_type()); - - std::vector<uint32_t> element_ids; - const analysis::Constant* length_const = - const_mgr->FindDeclaredConstant(original_array_type->LengthId()); - assert(length_const->AsIntConstant()); - uint32_t array_length = length_const->AsIntConstant()->GetU32(); - for (uint32_t i = 0; i < array_length; i++) { - Instruction* extract = ir_builder.AddCompositeExtract( - original_element_type_id, object_inst->result_id(), {i}); - element_ids.push_back( - GenerateCopy(extract, new_element_type_id, insertion_position)); - } - - return ir_builder.AddCompositeConstruct(new_type_id, element_ids) - ->result_id(); - } else if (const analysis::Struct* original_struct_type = - original_type->AsStruct()) { - analysis::Struct* new_struct_type = new_type->AsStruct(); - - const std::vector<const analysis::Type*>& original_types = - original_struct_type->element_types(); - const std::vector<const analysis::Type*>& new_types = - new_struct_type->element_types(); - std::vector<uint32_t> element_ids; - for (uint32_t i = 0; i < original_types.size(); i++) { - Instruction* extract = ir_builder.AddCompositeExtract( - type_mgr->GetId(original_types[i]), object_inst->result_id(), {i}); - element_ids.push_back(GenerateCopy(extract, type_mgr->GetId(new_types[i]), - insertion_position)); +uint32_t CopyPropagateArrays::GetMemberTypeId( + uint32_t id, const std::vector<uint32_t>& access_chain) const { + for (uint32_t element_index : access_chain) { + Instruction* type_inst = get_def_use_mgr()->GetDef(id); + switch (type_inst->opcode()) { + case SpvOpTypeArray: + case SpvOpTypeRuntimeArray: + case SpvOpTypeMatrix: + case SpvOpTypeVector: + id = type_inst->GetSingleWordInOperand(0); + break; + case SpvOpTypeStruct: + id = type_inst->GetSingleWordInOperand(element_index); + break; + default: + break; } - return ir_builder.AddCompositeConstruct(new_type_id, element_ids) - ->result_id(); - } else { - // If we do not have an aggregate type, then we have a problem. Either we - // found multiple instances of the same type, or we are copying to an - // incompatible type. Either way the code is illegal. - assert(false && - "Don't know how to copy this type. Code is likely illegal."); + assert(id != 0 && + "Tried to extract from an object where it cannot be done."); } - return 0; + return id; } -void CopyPropagateArrays::MemoryObject::GetMember( - const std::vector<uint32_t>& access_chain) { +void CopyPropagateArrays::MemoryObject::PushIndirection( + const std::vector<AccessChainEntry>& access_chain) { access_chain_.insert(access_chain_.end(), access_chain.begin(), access_chain.end()); } @@ -790,8 +806,8 @@ uint32_t CopyPropagateArrays::MemoryObject::GetNumberOfMembers() { const analysis::Constant* length_const = context->get_constant_mgr()->FindDeclaredConstant( array_type->LengthId()); - assert(length_const->AsIntConstant()); - return length_const->AsIntConstant()->GetU32(); + assert(length_const->type()->AsInteger()); + return length_const->GetU32(); } else if (const analysis::Vector* vector_type = type->AsVector()) { return vector_type->element_count(); } else if (const analysis::Matrix* matrix_type = type->AsMatrix()) { @@ -804,24 +820,29 @@ uint32_t CopyPropagateArrays::MemoryObject::GetNumberOfMembers() { template <class iterator> CopyPropagateArrays::MemoryObject::MemoryObject(Instruction* var_inst, iterator begin, iterator end) - : variable_inst_(var_inst), access_chain_(begin, end) {} + : variable_inst_(var_inst) { + std::transform(begin, end, std::back_inserter(access_chain_), + [](uint32_t id) { + return AccessChainEntry{true, {id}}; + }); +} std::vector<uint32_t> CopyPropagateArrays::MemoryObject::GetAccessIds() const { analysis::ConstantManager* const_mgr = variable_inst_->context()->get_constant_mgr(); - std::vector<uint32_t> access_indices; - for (uint32_t id : AccessChain()) { - const analysis::Constant* element_index_const = - const_mgr->FindDeclaredConstant(id); - if (!element_index_const) { - access_indices.push_back(0); - } else { - assert(element_index_const->AsIntConstant()); - access_indices.push_back(element_index_const->AsIntConstant()->GetU32()); - } - } - return access_indices; + std::vector<uint32_t> indices(AccessChain().size()); + std::transform(AccessChain().cbegin(), AccessChain().cend(), indices.begin(), + [&const_mgr](const AccessChainEntry& entry) { + if (entry.is_result_id) { + const analysis::Constant* constant = + const_mgr->FindDeclaredConstant(entry.result_id); + return constant == nullptr ? 0 : constant->GetU32(); + } + + return entry.immediate; + }); + return indices; } bool CopyPropagateArrays::MemoryObject::Contains( @@ -842,5 +863,24 @@ bool CopyPropagateArrays::MemoryObject::Contains( return true; } +void CopyPropagateArrays::MemoryObject::BuildConstants() { + for (auto& entry : access_chain_) { + if (entry.is_result_id) { + continue; + } + + auto context = variable_inst_->context(); + analysis::Integer int_type(32, false); + const analysis::Type* uint32_type = + context->get_type_mgr()->GetRegisteredType(&int_type); + analysis::ConstantManager* const_mgr = context->get_constant_mgr(); + const analysis::Constant* index_const = + const_mgr->GetConstant(uint32_type, {entry.immediate}); + entry.result_id = + const_mgr->GetDefiningInstruction(index_const)->result_id(); + entry.is_result_id = true; + } +} + } // namespace opt } // namespace spvtools |