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.");
const std::string extension_name = inst.GetInOperand(0).AsString();
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;
}
}

View File

@ -39,6 +39,13 @@ bool ConvertToHalfPass::IsFloat(Instruction* inst, uint32_t 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) {
uint32_t r_id = inst->result_id();
for (auto r_inst : get_decoration_mgr()->GetDecorationsFor(r_id, false))
@ -294,6 +301,7 @@ bool ConvertToHalfPass::CloseRelaxInst(Instruction* inst) {
bool relax = true;
inst->ForEachInId([&relax, this](uint32_t* idp) {
Instruction* op_inst = get_def_use_mgr()->GetDef(*idp);
if (IsStruct(op_inst)) relax = false;
if (!IsFloat(op_inst, 32)) return;
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
// float and |width|
bool IsFloat(Instruction* inst, uint32_t width);
bool IsStruct(Instruction* inst);
// Return true if |inst| is decorated with RelaxedPrecision
bool IsDecoratedRelaxed(Instruction* inst);

View File

@ -466,9 +466,9 @@ void ScalarReplacementPass::TransferAnnotations(
}
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) {
uint32_t ptrId = GetOrCreatePointerType(typeId);
uint32_t ptr_id = GetOrCreatePointerType(type_id);
uint32_t id = TakeNextId();
if (id == 0) {
@ -476,51 +476,22 @@ void ScalarReplacementPass::CreateVariable(
}
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>{
{SPV_OPERAND_TYPE_STORAGE_CLASS,
{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));
Instruction* inst = &*block->begin();
// 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);
context()->set_instr_block(inst, block);
// Copy decorations from the member to the new variable.
Instruction* typeInst = GetStorageType(varInst);
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);
CopyDecorationsToVariable(var_inst, inst, index);
inst->UpdateDebugInfoFrom(var_inst);
replacements->push_back(inst);
}
@ -529,52 +500,11 @@ uint32_t ScalarReplacementPass::GetOrCreatePointerType(uint32_t id) {
auto iter = pointee_to_pointer_.find(id);
if (iter != pointee_to_pointer_.end()) return iter->second;
analysis::Type* pointeeTy;
std::unique_ptr<analysis::Pointer> pointerTy;
std::tie(pointeeTy, pointerTy) =
context()->get_type_mgr()->GetTypeAndPointerType(
id, spv::StorageClass::Function);
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;
analysis::TypeManager* type_mgr = context()->get_type_mgr();
uint32_t ptr_type_id =
type_mgr->FindPointerToType(id, spv::StorageClass::Function);
pointee_to_pointer_[id] = ptr_type_id;
return ptr_type_id;
}
void ScalarReplacementPass::GetOrCreateInitialValue(Instruction* source,
@ -761,6 +691,8 @@ bool ScalarReplacementPass::CheckTypeAnnotations(
case spv::Decoration::AlignmentId:
case spv::Decoration::MaxByteOffset:
case spv::Decoration::RelaxedPrecision:
case spv::Decoration::AliasedPointer:
case spv::Decoration::RestrictPointer:
break;
default:
return false;
@ -781,6 +713,8 @@ bool ScalarReplacementPass::CheckAnnotations(const Instruction* varInst) const {
case spv::Decoration::Alignment:
case spv::Decoration::AlignmentId:
case spv::Decoration::MaxByteOffset:
case spv::Decoration::AliasedPointer:
case spv::Decoration::RestrictPointer:
break;
default:
return false;
@ -1011,5 +945,69 @@ uint64_t ScalarReplacementPass::GetMaxLegalIndex(
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 spvtools

View File

@ -262,9 +262,26 @@ class ScalarReplacementPass : public MemPass {
// that we will be willing to split.
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.
// 0 means there is no limit.
uint32_t max_num_elements_;
// 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
// terminating nul.

View File

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

View File

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

View File

@ -148,12 +148,16 @@ class Type {
// Returns a clone of |this| minus any decorations.
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
// unique.
// TODO(alanbaker): Update this if variable pointers become a core feature.
bool IsUniqueType(bool allowVariablePointers = false) const;
// %1 = OpTypeStruct %int
// %2 = OpTypeStruct %int
//
// 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;