1// Copyright (c) 2019 Google LLC
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#ifndef SOURCE_OPT_DESC_SROA_H_
16#define SOURCE_OPT_DESC_SROA_H_
17
18#include <cstdio>
19#include <memory>
20#include <queue>
21#include <unordered_map>
22#include <unordered_set>
23#include <vector>
24
25#include "source/opt/function.h"
26#include "source/opt/pass.h"
27#include "source/opt/type_manager.h"
28
29namespace spvtools {
30namespace opt {
31
32// Documented in optimizer.hpp
33class DescriptorScalarReplacement : public Pass {
34 public:
35 DescriptorScalarReplacement() {}
36
37 const char* name() const override { return "descriptor-scalar-replacement"; }
38
39 Status Process() override;
40
41 IRContext::Analysis GetPreservedAnalyses() override {
42 return IRContext::kAnalysisDefUse |
43 IRContext::kAnalysisInstrToBlockMapping |
44 IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG |
45 IRContext::kAnalysisConstants | IRContext::kAnalysisTypes;
46 }
47
48 private:
49 // Returns true if |var| is an OpVariable instruction that represents a
50 // descriptor array. These are the variables that we want to replace.
51 bool IsCandidate(Instruction* var);
52
53 // Replaces all references to |var| by new variables, one for each element of
54 // the array |var|. The binding for the new variables corresponding to
55 // element i will be the binding of |var| plus i. Returns true if successful.
56 bool ReplaceCandidate(Instruction* var);
57
58 // Replaces the base address |var| in the OpAccessChain or
59 // OpInBoundsAccessChain instruction |use| by the variable that the access
60 // chain accesses. The first index in |use| must be an |OpConstant|. Returns
61 // |true| if successful.
62 bool ReplaceAccessChain(Instruction* var, Instruction* use);
63
64 // Returns the id of the variable that will be used to replace the |idx|th
65 // element of |var|. The variable is created if it has not already been
66 // created.
67 uint32_t GetReplacementVariable(Instruction* var, uint32_t idx);
68
69 // Returns the id of a new variable that can be used to replace the |idx|th
70 // element of |var|.
71 uint32_t CreateReplacementVariable(Instruction* var, uint32_t idx);
72
73 // A map from an OpVariable instruction to the set of variables that will be
74 // used to replace it. The entry |replacement_variables_[var][i]| is the id of
75 // a variable that will be used in the place of the the ith element of the
76 // array |var|. If the entry is |0|, then the variable has not been
77 // created yet.
78 std::map<Instruction*, std::vector<uint32_t>> replacement_variables_;
79};
80
81} // namespace opt
82} // namespace spvtools
83
84#endif // SOURCE_OPT_DESC_SROA_H_
85