mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-11-23 04:00:05 +00:00
0741f42738
If the body of the module does not have any ids change, compact ids will not change the id bound. This can cause problems because the id bound could be much higher than the largest id in that is used. It should be reset any time it is not the larger id used + 1. Fixes #4604
102 lines
3.4 KiB
C++
102 lines
3.4 KiB
C++
// Copyright (c) 2017 Google Inc.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#include "source/opt/compact_ids_pass.h"
|
|
|
|
#include <cassert>
|
|
#include <unordered_map>
|
|
|
|
#include "source/opt/ir_context.h"
|
|
|
|
namespace spvtools {
|
|
namespace opt {
|
|
namespace {
|
|
|
|
// Returns the remapped id of |id| from |result_id_mapping|. If the remapped
|
|
// id does not exist, adds a new one to |result_id_mapping| and returns it.
|
|
uint32_t GetRemappedId(
|
|
std::unordered_map<uint32_t, uint32_t>* result_id_mapping, uint32_t id) {
|
|
auto it = result_id_mapping->find(id);
|
|
if (it == result_id_mapping->end()) {
|
|
const uint32_t new_id =
|
|
static_cast<uint32_t>(result_id_mapping->size()) + 1;
|
|
const auto insertion_result = result_id_mapping->emplace(id, new_id);
|
|
it = insertion_result.first;
|
|
assert(insertion_result.second);
|
|
}
|
|
return it->second;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
Pass::Status CompactIdsPass::Process() {
|
|
bool modified = false;
|
|
std::unordered_map<uint32_t, uint32_t> result_id_mapping;
|
|
|
|
context()->module()->ForEachInst(
|
|
[&result_id_mapping, &modified](Instruction* inst) {
|
|
auto operand = inst->begin();
|
|
while (operand != inst->end()) {
|
|
const auto type = operand->type;
|
|
if (spvIsIdType(type)) {
|
|
assert(operand->words.size() == 1);
|
|
uint32_t& id = operand->words[0];
|
|
uint32_t new_id = GetRemappedId(&result_id_mapping, id);
|
|
if (id != new_id) {
|
|
modified = true;
|
|
id = new_id;
|
|
// Update data cached in the instruction object.
|
|
if (type == SPV_OPERAND_TYPE_RESULT_ID) {
|
|
inst->SetResultId(id);
|
|
} else if (type == SPV_OPERAND_TYPE_TYPE_ID) {
|
|
inst->SetResultType(id);
|
|
}
|
|
}
|
|
}
|
|
++operand;
|
|
}
|
|
|
|
uint32_t scope_id = inst->GetDebugScope().GetLexicalScope();
|
|
if (scope_id != kNoDebugScope) {
|
|
uint32_t new_id = GetRemappedId(&result_id_mapping, scope_id);
|
|
if (scope_id != new_id) {
|
|
inst->UpdateLexicalScope(new_id);
|
|
modified = true;
|
|
}
|
|
}
|
|
uint32_t inlinedat_id = inst->GetDebugInlinedAt();
|
|
if (inlinedat_id != kNoInlinedAt) {
|
|
uint32_t new_id = GetRemappedId(&result_id_mapping, inlinedat_id);
|
|
if (inlinedat_id != new_id) {
|
|
inst->UpdateDebugInlinedAt(new_id);
|
|
modified = true;
|
|
}
|
|
}
|
|
},
|
|
true);
|
|
|
|
if (context()->module()->id_bound() != result_id_mapping.size() + 1) {
|
|
modified = true;
|
|
context()->module()->SetIdBound(
|
|
static_cast<uint32_t>(result_id_mapping.size() + 1));
|
|
// There are ids in the feature manager that could now be invalid
|
|
context()->ResetFeatureManager();
|
|
}
|
|
|
|
return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
|
|
}
|
|
|
|
} // namespace opt
|
|
} // namespace spvtools
|