Updated spirv-tools.

This commit is contained in:
Бранимир Караџић 2023-05-14 08:48:28 -07:00
parent a3598c6d28
commit 2d3a057a68
9 changed files with 121 additions and 93 deletions

View File

@ -1 +1 @@
"v2023.2", "SPIRV-Tools v2023.2 v2022.4-192-ge472626b" "v2023.2", "SPIRV-Tools v2023.2 v2022.4-196-g1b88382e"

View File

@ -156,7 +156,8 @@ bool AggressiveDCEPass::AllExtensionsSupported() const {
"Expecting an import of an extension's instruction set."); "Expecting an import of an extension's instruction set.");
const std::string extension_name = inst.GetInOperand(0).AsString(); const std::string extension_name = inst.GetInOperand(0).AsString();
if (spvtools::utils::starts_with(extension_name, "NonSemantic.") && if (spvtools::utils::starts_with(extension_name, "NonSemantic.") &&
extension_name != "NonSemantic.Shader.DebugInfo.100") { (extension_name != "NonSemantic.Shader.DebugInfo.100") &&
(extension_name != "NonSemantic.DebugPrintf")) {
return false; return false;
} }
} }

View File

@ -39,6 +39,13 @@ bool ConvertToHalfPass::IsFloat(Instruction* inst, uint32_t width) {
return Pass::IsFloat(ty_id, width); return Pass::IsFloat(ty_id, width);
} }
bool ConvertToHalfPass::IsStruct(Instruction* inst) {
uint32_t ty_id = inst->type_id();
if (ty_id == 0) return false;
Instruction* ty_inst = Pass::GetBaseType(ty_id);
return (ty_inst->opcode() == spv::Op::OpTypeStruct);
}
bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) { bool ConvertToHalfPass::IsDecoratedRelaxed(Instruction* inst) {
uint32_t r_id = inst->result_id(); uint32_t r_id = inst->result_id();
for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false)) for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
@ -294,6 +301,7 @@ bool ConvertToHalfPass::CloseRelaxInst(Instruction* inst) {
bool relax = true; bool relax = true;
inst->ForEachInId([&relax, this](uint32_t* idp) { inst->ForEachInId([&relax, this](uint32_t* idp) {
Instruction* op_inst = get_def_use_mgr()->GetDef(*idp); Instruction* op_inst = get_def_use_mgr()->GetDef(*idp);
if (IsStruct(op_inst)) relax = false;
if (!IsFloat(op_inst, 32)) return; if (!IsFloat(op_inst, 32)) return;
if (!IsRelaxed(*idp)) relax = false; if (!IsRelaxed(*idp)) relax = false;
}); });

View File

@ -45,6 +45,7 @@ class ConvertToHalfPass : public Pass {
// Return true if |inst| returns scalar, vector or matrix type with base // Return true if |inst| returns scalar, vector or matrix type with base
// float and |width| // float and |width|
bool IsFloat(Instruction* inst, uint32_t width); bool IsFloat(Instruction* inst, uint32_t width);
bool IsStruct(Instruction* inst);
// Return true if |inst| is decorated with RelaxedPrecision // Return true if |inst| is decorated with RelaxedPrecision
bool IsDecoratedRelaxed(Instruction* inst); bool IsDecoratedRelaxed(Instruction* inst);

View File

@ -466,9 +466,9 @@ void ScalarReplacementPass::TransferAnnotations(
} }
void ScalarReplacementPass::CreateVariable( void ScalarReplacementPass::CreateVariable(
uint32_t typeId, Instruction* varInst, uint32_t index, uint32_t type_id, Instruction* var_inst, uint32_t index,
std::vector<Instruction*>* replacements) { std::vector<Instruction*>* replacements) {
uint32_t ptrId = GetOrCreatePointerType(typeId); uint32_t ptr_id = GetOrCreatePointerType(type_id);
uint32_t id = TakeNextId(); uint32_t id = TakeNextId();
if (id == 0) { if (id == 0) {
@ -476,51 +476,22 @@ void ScalarReplacementPass::CreateVariable(
} }
std::unique_ptr<Instruction> variable( std::unique_ptr<Instruction> variable(
new Instruction(context(), spv::Op::OpVariable, ptrId, id, new Instruction(context(), spv::Op::OpVariable, ptr_id, id,
std::initializer_list<Operand>{ std::initializer_list<Operand>{
{SPV_OPERAND_TYPE_STORAGE_CLASS, {SPV_OPERAND_TYPE_STORAGE_CLASS,
{uint32_t(spv::StorageClass::Function)}}})); {uint32_t(spv::StorageClass::Function)}}}));
BasicBlock* block = context()->get_instr_block(varInst); BasicBlock* block = context()->get_instr_block(var_inst);
block->begin().InsertBefore(std::move(variable)); block->begin().InsertBefore(std::move(variable));
Instruction* inst = &*block->begin(); Instruction* inst = &*block->begin();
// If varInst was initialized, make sure to initialize its replacement. // If varInst was initialized, make sure to initialize its replacement.
GetOrCreateInitialValue(varInst, index, inst); GetOrCreateInitialValue(var_inst, index, inst);
get_def_use_mgr()->AnalyzeInstDefUse(inst); get_def_use_mgr()->AnalyzeInstDefUse(inst);
context()->set_instr_block(inst, block); context()->set_instr_block(inst, block);
// Copy decorations from the member to the new variable. CopyDecorationsToVariable(var_inst, inst, index);
Instruction* typeInst = GetStorageType(varInst); inst->UpdateDebugInfoFrom(var_inst);
for (auto dec_inst :
get_decoration_mgr()->GetDecorationsFor(typeInst->result_id(), false)) {
uint32_t decoration;
if (dec_inst->opcode() != spv::Op::OpMemberDecorate) {
continue;
}
if (dec_inst->GetSingleWordInOperand(1) != index) {
continue;
}
decoration = dec_inst->GetSingleWordInOperand(2u);
switch (spv::Decoration(decoration)) {
case spv::Decoration::RelaxedPrecision: {
std::unique_ptr<Instruction> new_dec_inst(
new Instruction(context(), spv::Op::OpDecorate, 0, 0, {}));
new_dec_inst->AddOperand(Operand(SPV_OPERAND_TYPE_ID, {id}));
for (uint32_t i = 2; i < dec_inst->NumInOperandWords(); ++i) {
new_dec_inst->AddOperand(Operand(dec_inst->GetInOperand(i)));
}
context()->AddAnnotationInst(std::move(new_dec_inst));
} break;
default:
break;
}
}
// Update the DebugInfo debug information.
inst->UpdateDebugInfoFrom(varInst);
replacements->push_back(inst); replacements->push_back(inst);
} }
@ -529,52 +500,11 @@ uint32_t ScalarReplacementPass::GetOrCreatePointerType(uint32_t id) {
auto iter = pointee_to_pointer_.find(id); auto iter = pointee_to_pointer_.find(id);
if (iter != pointee_to_pointer_.end()) return iter->second; if (iter != pointee_to_pointer_.end()) return iter->second;
analysis::Type* pointeeTy; analysis::TypeManager* type_mgr = context()->get_type_mgr();
std::unique_ptr<analysis::Pointer> pointerTy; uint32_t ptr_type_id =
std::tie(pointeeTy, pointerTy) = type_mgr->FindPointerToType(id, spv::StorageClass::Function);
context()->get_type_mgr()->GetTypeAndPointerType( pointee_to_pointer_[id] = ptr_type_id;
id, spv::StorageClass::Function); return ptr_type_id;
uint32_t ptrId = 0;
if (pointeeTy->IsUniqueType()) {
// Non-ambiguous type, just ask the type manager for an id.
ptrId = context()->get_type_mgr()->GetTypeInstruction(pointerTy.get());
pointee_to_pointer_[id] = ptrId;
return ptrId;
}
// Ambiguous type. We must perform a linear search to try and find the right
// type.
for (auto global : context()->types_values()) {
if (global.opcode() == spv::Op::OpTypePointer &&
spv::StorageClass(global.GetSingleWordInOperand(0u)) ==
spv::StorageClass::Function &&
global.GetSingleWordInOperand(1u) == id) {
if (get_decoration_mgr()->GetDecorationsFor(id, false).empty()) {
// Only reuse a decoration-less pointer of the correct type.
ptrId = global.result_id();
break;
}
}
}
if (ptrId != 0) {
pointee_to_pointer_[id] = ptrId;
return ptrId;
}
ptrId = TakeNextId();
context()->AddType(MakeUnique<Instruction>(
context(), spv::Op::OpTypePointer, 0, ptrId,
std::initializer_list<Operand>{{SPV_OPERAND_TYPE_STORAGE_CLASS,
{uint32_t(spv::StorageClass::Function)}},
{SPV_OPERAND_TYPE_ID, {id}}}));
Instruction* ptr = &*--context()->types_values_end();
get_def_use_mgr()->AnalyzeInstDefUse(ptr);
pointee_to_pointer_[id] = ptrId;
// Register with the type manager if necessary.
context()->get_type_mgr()->RegisterType(ptrId, *pointerTy);
return ptrId;
} }
void ScalarReplacementPass::GetOrCreateInitialValue(Instruction* source, void ScalarReplacementPass::GetOrCreateInitialValue(Instruction* source,
@ -761,6 +691,8 @@ bool ScalarReplacementPass::CheckTypeAnnotations(
case spv::Decoration::AlignmentId: case spv::Decoration::AlignmentId:
case spv::Decoration::MaxByteOffset: case spv::Decoration::MaxByteOffset:
case spv::Decoration::RelaxedPrecision: case spv::Decoration::RelaxedPrecision:
case spv::Decoration::AliasedPointer:
case spv::Decoration::RestrictPointer:
break; break;
default: default:
return false; return false;
@ -781,6 +713,8 @@ bool ScalarReplacementPass::CheckAnnotations(const Instruction* varInst) const {
case spv::Decoration::Alignment: case spv::Decoration::Alignment:
case spv::Decoration::AlignmentId: case spv::Decoration::AlignmentId:
case spv::Decoration::MaxByteOffset: case spv::Decoration::MaxByteOffset:
case spv::Decoration::AliasedPointer:
case spv::Decoration::RestrictPointer:
break; break;
default: default:
return false; return false;
@ -1011,5 +945,69 @@ uint64_t ScalarReplacementPass::GetMaxLegalIndex(
return 0; return 0;
} }
void ScalarReplacementPass::CopyDecorationsToVariable(Instruction* from,
Instruction* to,
uint32_t member_index) {
CopyPointerDecorationsToVariable(from, to);
CopyNecessaryMemberDecorationsToVariable(from, to, member_index);
}
void ScalarReplacementPass::CopyPointerDecorationsToVariable(Instruction* from,
Instruction* to) {
// The RestrictPointer and AliasedPointer decorations are copied to all
// members even if the new variable does not contain a pointer. It does
// not hurt to do so.
for (auto dec_inst :
get_decoration_mgr()->GetDecorationsFor(from->result_id(), false)) {
uint32_t decoration;
decoration = dec_inst->GetSingleWordInOperand(1u);
switch (spv::Decoration(decoration)) {
case spv::Decoration::AliasedPointer:
case spv::Decoration::RestrictPointer: {
std::unique_ptr<Instruction> new_dec_inst(dec_inst->Clone(context()));
new_dec_inst->SetInOperand(0, {to->result_id()});
context()->AddAnnotationInst(std::move(new_dec_inst));
} break;
default:
break;
}
}
}
void ScalarReplacementPass::CopyNecessaryMemberDecorationsToVariable(
Instruction* from, Instruction* to, uint32_t member_index) {
Instruction* type_inst = GetStorageType(from);
for (auto dec_inst :
get_decoration_mgr()->GetDecorationsFor(type_inst->result_id(), false)) {
uint32_t decoration;
if (dec_inst->opcode() == spv::Op::OpMemberDecorate) {
if (dec_inst->GetSingleWordInOperand(1) != member_index) {
continue;
}
decoration = dec_inst->GetSingleWordInOperand(2u);
switch (spv::Decoration(decoration)) {
case spv::Decoration::ArrayStride:
case spv::Decoration::Alignment:
case spv::Decoration::AlignmentId:
case spv::Decoration::MaxByteOffset:
case spv::Decoration::MaxByteOffsetId:
case spv::Decoration::RelaxedPrecision: {
std::unique_ptr<Instruction> new_dec_inst(
new Instruction(context(), spv::Op::OpDecorate, 0, 0, {}));
new_dec_inst->AddOperand(
Operand(SPV_OPERAND_TYPE_ID, {to->result_id()}));
for (uint32_t i = 2; i < dec_inst->NumInOperandWords(); ++i) {
new_dec_inst->AddOperand(Operand(dec_inst->GetInOperand(i)));
}
context()->AddAnnotationInst(std::move(new_dec_inst));
} break;
default:
break;
}
}
}
}
} // namespace opt } // namespace opt
} // namespace spvtools } // namespace spvtools

View File

@ -262,9 +262,26 @@ class ScalarReplacementPass : public MemPass {
// that we will be willing to split. // that we will be willing to split.
bool IsLargerThanSizeLimit(uint64_t length) const; bool IsLargerThanSizeLimit(uint64_t length) const;
// Copies all relevant decorations from `from` to `to`. This includes
// decorations applied to the variable, and to the members of the type.
// It is assumed that `to` is a variable that is intended to replace the
// `member_index`th member of `from`.
void CopyDecorationsToVariable(Instruction* from, Instruction* to,
uint32_t member_index);
// Copies pointer related decoration from `from` to `to` if they exist.
void CopyPointerDecorationsToVariable(Instruction* from, Instruction* to);
// Copies decorations that are needed from the `member_index` of `from` to
// `to, if there was one.
void CopyNecessaryMemberDecorationsToVariable(Instruction* from,
Instruction* to,
uint32_t member_index);
// Limit on the number of members in an object that will be replaced. // Limit on the number of members in an object that will be replaced.
// 0 means there is no limit. // 0 means there is no limit.
uint32_t max_num_elements_; uint32_t max_num_elements_;
// This has to be big enough to fit "scalar-replacement=" followed by a // This has to be big enough to fit "scalar-replacement=" followed by a
// uint32_t number written in decimal (so 10 digits), and then a // uint32_t number written in decimal (so 10 digits), and then a
// terminating nul. // terminating nul.

View File

@ -178,7 +178,7 @@ void TypeManager::RemoveId(uint32_t id) {
if (iter == id_to_type_.end()) return; if (iter == id_to_type_.end()) return;
auto& type = iter->second; auto& type = iter->second;
if (!type->IsUniqueType(true)) { if (!type->IsUniqueType()) {
auto tIter = type_to_id_.find(type); auto tIter = type_to_id_.find(type);
if (tIter != type_to_id_.end() && tIter->second == id) { if (tIter != type_to_id_.end() && tIter->second == id) {
// |type| currently maps to |id|. // |type| currently maps to |id|.
@ -437,7 +437,7 @@ uint32_t TypeManager::FindPointerToType(uint32_t type_id,
spv::StorageClass storage_class) { spv::StorageClass storage_class) {
Type* pointeeTy = GetType(type_id); Type* pointeeTy = GetType(type_id);
Pointer pointerTy(pointeeTy, storage_class); Pointer pointerTy(pointeeTy, storage_class);
if (pointeeTy->IsUniqueType(true)) { if (pointeeTy->IsUniqueType()) {
// Non-ambiguous type. Get the pointer type through the type manager. // Non-ambiguous type. Get the pointer type through the type manager.
return GetTypeInstruction(&pointerTy); return GetTypeInstruction(&pointerTy);
} }

View File

@ -84,10 +84,9 @@ bool Type::HasSameDecorations(const Type* that) const {
return CompareTwoVectors(decorations_, that->decorations_); return CompareTwoVectors(decorations_, that->decorations_);
} }
bool Type::IsUniqueType(bool allowVariablePointers) const { bool Type::IsUniqueType() const {
switch (kind_) { switch (kind_) {
case kPointer: case kPointer:
return !allowVariablePointers;
case kStruct: case kStruct:
case kArray: case kArray:
case kRuntimeArray: case kRuntimeArray:

View File

@ -148,12 +148,16 @@ class Type {
// Returns a clone of |this| minus any decorations. // Returns a clone of |this| minus any decorations.
std::unique_ptr<Type> RemoveDecorations() const; std::unique_ptr<Type> RemoveDecorations() const;
// Returns true if this type must be unique. // Returns true if this cannot hash to the same value as another type in the
// module. For example, structs are not unique types because the module could
// have two types
// //
// If variable pointers are allowed, then pointers are not required to be // %1 = OpTypeStruct %int
// unique. // %2 = OpTypeStruct %int
// TODO(alanbaker): Update this if variable pointers become a core feature. //
bool IsUniqueType(bool allowVariablePointers = false) const; // The only way to distinguish these types is the result id. The type manager
// will hash them to the same value.
bool IsUniqueType() const;
bool operator==(const Type& other) const; bool operator==(const Type& other) const;