1// Copyright (c) 2018 The Khronos Group Inc.
2// Copyright (c) 2018 Valve Corporation
3// Copyright (c) 2018 LunarG Inc.
4//
5// Licensed under the Apache License, Version 2.0 (the "License");
6// you may not use this file except in compliance with the License.
7// You may obtain a copy of the License at
8//
9// http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing, software
12// distributed under the License is distributed on an "AS IS" BASIS,
13// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14// See the License for the specific language governing permissions and
15// limitations under the License.
16
17#ifndef SOURCE_OPT_DEAD_INSERT_ELIM_PASS_H_
18#define SOURCE_OPT_DEAD_INSERT_ELIM_PASS_H_
19
20#include <algorithm>
21#include <map>
22#include <unordered_map>
23#include <unordered_set>
24#include <utility>
25#include <vector>
26
27#include "source/opt/basic_block.h"
28#include "source/opt/def_use_manager.h"
29#include "source/opt/ir_context.h"
30#include "source/opt/mem_pass.h"
31#include "source/opt/module.h"
32
33namespace spvtools {
34namespace opt {
35
36// See optimizer.hpp for documentation.
37class DeadInsertElimPass : public MemPass {
38 public:
39 DeadInsertElimPass() = default;
40
41 const char* name() const override { return "eliminate-dead-inserts"; }
42 Status Process() override;
43 IRContext::Analysis GetPreservedAnalyses() override {
44 return IRContext::kAnalysisDefUse |
45 IRContext::kAnalysisInstrToBlockMapping |
46 IRContext::kAnalysisDecorations | IRContext::kAnalysisCombinators |
47 IRContext::kAnalysisCFG | IRContext::kAnalysisDominatorAnalysis |
48 IRContext::kAnalysisNameMap | IRContext::kAnalysisConstants |
49 IRContext::kAnalysisTypes;
50 }
51
52 private:
53 // Return the number of subcomponents in the composite type |typeId|.
54 // Return 0 if not a composite type or number of components is not a
55 // 32-bit constant.
56 uint32_t NumComponents(Instruction* typeInst);
57
58 // Mark all inserts in instruction chain ending at |insertChain| with
59 // indices that intersect with extract indices |extIndices| starting with
60 // index at |extOffset|. Chains are composed solely of Inserts and Phis.
61 // Mark all inserts in chain if |extIndices| is nullptr.
62 void MarkInsertChain(Instruction* insertChain,
63 std::vector<uint32_t>* extIndices, uint32_t extOffset,
64 std::unordered_set<uint32_t>* visited_phis);
65
66 // Perform EliminateDeadInsertsOnePass(|func|) until no modification is
67 // made. Return true if modified.
68 bool EliminateDeadInserts(Function* func);
69
70 // DCE all dead struct, matrix and vector inserts in |func|. An insert is
71 // dead if the value it inserts is never used. Replace any reference to the
72 // insert with its original composite. Return true if modified. Dead inserts
73 // in dependence cycles are not currently eliminated. Dead inserts into
74 // arrays are not currently eliminated.
75 bool EliminateDeadInsertsOnePass(Function* func);
76
77 // Return true if all extensions in this module are allowed by this pass.
78 bool AllExtensionsSupported() const;
79
80 // Live inserts
81 std::unordered_set<uint32_t> liveInserts_;
82
83 // Visited phis as insert chain is traversed; used to avoid infinite loop
84 std::unordered_map<uint32_t, bool> visitedPhis_;
85};
86
87} // namespace opt
88} // namespace spvtools
89
90#endif // SOURCE_OPT_DEAD_INSERT_ELIM_PASS_H_
91