SPIRV-Tools/source/opt/block_merge_pass.h
Steven Perron ddc705933d
Analyze uses for all instructions. (#1937)
* Analyze uses for all instructions.

The def-use manager needs to fill in the `inst_to_used_ids_` field for
every instruction.  This means we have to analyze the uses for every
instruction, even if they do not have any uses.

This mistake was not found earlier because there was a typo in the
equality check for def-use managers.  No new tests are needed.

While looking into this I found redundant work in block merge.  Cleaning
that up at the same time.

* Fix other transformations

Aggressive dead code elimination did not update the OpGroupDecorate
and the OpGroupMemberDecorate instructions properly when they are
updated.  That is fixed.

Dead branch elimination did not analyze the OpUnreachable instructions
that is would add.  That is taken care of.
2018-09-28 14:39:06 -04:00

70 lines
2.1 KiB
C++

// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2017 Valve Corporation
// Copyright (c) 2017 LunarG 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.
#ifndef SOURCE_OPT_BLOCK_MERGE_PASS_H_
#define SOURCE_OPT_BLOCK_MERGE_PASS_H_
#include <algorithm>
#include <map>
#include <queue>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include "source/opt/basic_block.h"
#include "source/opt/def_use_manager.h"
#include "source/opt/ir_context.h"
#include "source/opt/module.h"
#include "source/opt/pass.h"
namespace spvtools {
namespace opt {
// See optimizer.hpp for documentation.
class BlockMergePass : public Pass {
public:
BlockMergePass();
const char* name() const override { return "merge-blocks"; }
Status Process() override;
IRContext::Analysis GetPreservedAnalyses() override {
return IRContext::kAnalysisDefUse |
IRContext::kAnalysisInstrToBlockMapping |
IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
IRContext::kAnalysisNameMap;
}
private:
// Search |func| for blocks which have a single Branch to a block
// with no other predecessors. Merge these blocks into a single block.
bool MergeBlocks(Function* func);
// Returns true if |block| (or |id|) contains a merge instruction.
bool IsHeader(BasicBlock* block);
bool IsHeader(uint32_t id);
// Returns true if |block| (or |id|) is the merge target of a merge
// instruction.
bool IsMerge(BasicBlock* block);
bool IsMerge(uint32_t id);
};
} // namespace opt
} // namespace spvtools
#endif // SOURCE_OPT_BLOCK_MERGE_PASS_H_