summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/bgfx/3rdparty/spirv-tools/source/opt/copy_prop_arrays.cpp
diff options
context:
space:
mode:
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.cpp516
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