mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-19 19:40:13 +00:00
6679d5df89
Add a pass for spirv-reduce that will turn a loop into a selection.
96 lines
3.3 KiB
C++
96 lines
3.3 KiB
C++
// Copyright (c) 2018 Google LLC
|
|
//
|
|
// 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 "structured_loop_to_selection_reduction_pass.h"
|
|
#include "structured_loop_to_selection_reduction_opportunity.h"
|
|
|
|
namespace spvtools {
|
|
namespace reduce {
|
|
|
|
using namespace opt;
|
|
|
|
namespace {
|
|
const uint32_t kMergeNodeIndex = 0;
|
|
const uint32_t kContinueNodeIndex = 1;
|
|
} // namespace
|
|
|
|
std::vector<std::unique_ptr<ReductionOpportunity>>
|
|
StructuredLoopToSelectionReductionPass::GetAvailableOpportunities(
|
|
opt::IRContext* context) const {
|
|
std::vector<std::unique_ptr<ReductionOpportunity>> result;
|
|
|
|
std::set<uint32_t> merge_block_ids;
|
|
for (auto& function : *context->module()) {
|
|
for (auto& block : function) {
|
|
auto merge_inst = block.GetMergeInst();
|
|
if (merge_inst) {
|
|
merge_block_ids.insert(
|
|
merge_inst->GetSingleWordOperand(kMergeNodeIndex));
|
|
}
|
|
}
|
|
}
|
|
|
|
// Consider each loop construct header in the module.
|
|
for (auto& function : *context->module()) {
|
|
for (auto& block : function) {
|
|
auto loop_merge_inst = block.GetLoopMergeInst();
|
|
if (!loop_merge_inst) {
|
|
// This is not a loop construct header.
|
|
continue;
|
|
}
|
|
|
|
// Check whether the loop construct's continue target is the merge block
|
|
// of some structured control flow construct. If it is, we cautiously do
|
|
// not consider applying a transformation.
|
|
if (merge_block_ids.find(loop_merge_inst->GetSingleWordOperand(
|
|
kContinueNodeIndex)) != merge_block_ids.end()) {
|
|
continue;
|
|
}
|
|
|
|
// Check whether the loop construct header dominates its merge block.
|
|
// If not, the merge block must be unreachable in the control flow graph
|
|
// so we cautiously do not consider applying a transformation.
|
|
auto merge_block_id =
|
|
loop_merge_inst->GetSingleWordInOperand(kMergeNodeIndex);
|
|
if (!context->GetDominatorAnalysis(&function)->Dominates(
|
|
block.id(), merge_block_id)) {
|
|
continue;
|
|
}
|
|
|
|
// Check whether the loop construct merge block postdominates the loop
|
|
// construct header. If not (e.g. because the loop contains OpReturn,
|
|
// OpKill or OpUnreachable), we cautiously do not consider applying
|
|
// a transformation.
|
|
if (!context->GetPostDominatorAnalysis(&function)->Dominates(
|
|
merge_block_id, block.id())) {
|
|
continue;
|
|
}
|
|
|
|
// We can turn this structured loop into a selection, so add the
|
|
// opportunity to do so.
|
|
result.push_back(
|
|
MakeUnique<StructuredLoopToSelectionReductionOpportunity>(
|
|
context, &block, &function));
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
std::string StructuredLoopToSelectionReductionPass::GetName() const {
|
|
return "StructuredLoopToSelectionReductionPass";
|
|
}
|
|
|
|
} // namespace reduce
|
|
} // namespace spvtools
|