/src/spirv-tools/source/opt/spread_volatile_semantics.h
Line | Count | Source (jump to first uncovered line) |
1 | | // Copyright (c) 2022 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_SPREAD_VOLATILE_SEMANTICS_H_ |
16 | | #define SOURCE_OPT_SPREAD_VOLATILE_SEMANTICS_H_ |
17 | | |
18 | | #include "source/opt/pass.h" |
19 | | |
20 | | namespace spvtools { |
21 | | namespace opt { |
22 | | |
23 | | // See optimizer.hpp for documentation. |
24 | | class SpreadVolatileSemantics : public Pass { |
25 | | public: |
26 | 0 | SpreadVolatileSemantics() {} |
27 | | |
28 | 0 | const char* name() const override { return "spread-volatile-semantics"; } |
29 | | |
30 | | Status Process() override; |
31 | | |
32 | 0 | IRContext::Analysis GetPreservedAnalyses() override { |
33 | 0 | return IRContext::kAnalysisDefUse | IRContext::kAnalysisDecorations | |
34 | 0 | IRContext::kAnalysisInstrToBlockMapping; |
35 | 0 | } |
36 | | |
37 | | private: |
38 | | // Returns true if it does not have an execution model. Linkage shaders do not |
39 | | // have an execution model. |
40 | 0 | bool HasNoExecutionModel() { |
41 | 0 | return get_module()->entry_points().empty() && |
42 | 0 | context()->get_feature_mgr()->HasCapability( |
43 | 0 | spv::Capability::Linkage); |
44 | 0 | } |
45 | | |
46 | | // Iterates interface variables and spreads the Volatile semantics if it has |
47 | | // load instructions for the Volatile semantics. |
48 | | Pass::Status SpreadVolatileSemanticsToVariables( |
49 | | const bool is_vk_memory_model_enabled); |
50 | | |
51 | | // Returns whether |var_id| is the result id of a target builtin variable for |
52 | | // the volatile semantics for |execution_model| based on the Vulkan spec |
53 | | // VUID-StandaloneSpirv-VulkanMemoryModel-04678 or |
54 | | // VUID-StandaloneSpirv-VulkanMemoryModel-04679. |
55 | | bool IsTargetForVolatileSemantics(uint32_t var_id, |
56 | | spv::ExecutionModel execution_model); |
57 | | |
58 | | // Collects interface variables that need the volatile semantics. |
59 | | // |is_vk_memory_model_enabled| is true if VulkanMemoryModel capability is |
60 | | // enabled. |
61 | | void CollectTargetsForVolatileSemantics( |
62 | | const bool is_vk_memory_model_enabled); |
63 | | |
64 | | // Reports an error if an interface variable is used by two entry points and |
65 | | // it needs the Volatile decoration for one but not for another. Returns true |
66 | | // if the error must be reported. |
67 | | bool HasInterfaceInConflictOfVolatileSemantics(); |
68 | | |
69 | | // Returns whether the variable whose result is |var_id| is used by a |
70 | | // non-volatile load or a pointer to it is used by a non-volatile load in |
71 | | // |entry_point| or not. |
72 | | bool IsTargetUsedByNonVolatileLoadInEntryPoint(uint32_t var_id, |
73 | | Instruction* entry_point); |
74 | | |
75 | | // Visits load instructions of pointers to variable whose result id is |
76 | | // |var_id| if the load instructions are in reachable functions from entry |
77 | | // points. |handle_load| is a function to do some actions for the load |
78 | | // instructions. Finishes the traversal and returns false if |handle_load| |
79 | | // returns false for a load instruction. Otherwise, returns true after running |
80 | | // |handle_load| for all the load instructions. |
81 | | bool VisitLoadsOfPointersToVariableInEntries( |
82 | | uint32_t var_id, const std::function<bool(Instruction*)>& handle_load, |
83 | | const std::unordered_set<uint32_t>& function_ids); |
84 | | |
85 | | // Sets Memory Operands of OpLoad instructions that load |var| or pointers |
86 | | // of |var| as Volatile if the function id of the OpLoad instruction is |
87 | | // included in |entry_function_ids|. |
88 | | void SetVolatileForLoadsInEntries( |
89 | | Instruction* var, const std::unordered_set<uint32_t>& entry_function_ids); |
90 | | |
91 | | // Adds OpDecorate Volatile for |var| if it does not exist. |
92 | | void DecorateVarWithVolatile(Instruction* var); |
93 | | |
94 | | // Returns a set of entry function ids to spread the volatile semantics for |
95 | | // the variable with the result id |var_id|. |
96 | | std::unordered_set<uint32_t> EntryFunctionsToSpreadVolatileSemanticsForVar( |
97 | 0 | uint32_t var_id) { |
98 | 0 | auto itr = var_ids_to_entry_fn_for_volatile_semantics_.find(var_id); |
99 | 0 | if (itr == var_ids_to_entry_fn_for_volatile_semantics_.end()) return {}; |
100 | 0 | return itr->second; |
101 | 0 | } |
102 | | |
103 | | // Specifies that we have to spread the volatile semantics for the |
104 | | // variable with the result id |var_id| for the entry point |entry_point|. |
105 | | void MarkVolatileSemanticsForVariable(uint32_t var_id, |
106 | | Instruction* entry_point); |
107 | | |
108 | | // Result ids of variables to entry function ids for the volatile semantics |
109 | | // spread. |
110 | | std::unordered_map<uint32_t, std::unordered_set<uint32_t>> |
111 | | var_ids_to_entry_fn_for_volatile_semantics_; |
112 | | }; |
113 | | |
114 | | } // namespace opt |
115 | | } // namespace spvtools |
116 | | |
117 | | #endif // SOURCE_OPT_SPREAD_VOLATILE_SEMANTICS_H_ |