decoration_manager.h 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // Copyright (c) 2017 Pierre Moreau
  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. #ifndef SOURCE_OPT_DECORATION_MANAGER_H_
  15. #define SOURCE_OPT_DECORATION_MANAGER_H_
  16. #include <functional>
  17. #include <unordered_map>
  18. #include <unordered_set>
  19. #include <vector>
  20. #include "source/opt/instruction.h"
  21. #include "source/opt/module.h"
  22. namespace spvtools {
  23. namespace opt {
  24. namespace analysis {
  25. // A class for analyzing and managing decorations in an Module.
  26. class DecorationManager {
  27. public:
  28. // Constructs a decoration manager from the given |module|
  29. explicit DecorationManager(Module* module) : module_(module) {
  30. AnalyzeDecorations();
  31. }
  32. DecorationManager() = delete;
  33. // Removes all decorations (direct and through groups) where |pred| is
  34. // true and that apply to |id| so that they no longer apply to |id|. Returns
  35. // true if something changed.
  36. //
  37. // If |id| is part of a group, it will be removed from the group if it
  38. // does not use all of the group's decorations, or, if there are no
  39. // decorations that apply to the group.
  40. //
  41. // If decoration groups become empty, the |OpGroupDecorate| and
  42. // |OpGroupMemberDecorate| instructions will be killed.
  43. //
  44. // Decoration instructions that apply directly to |id| will be killed.
  45. //
  46. // If |id| is a decoration group and all of the group's decorations are
  47. // removed, then the |OpGroupDecorate| and
  48. // |OpGroupMemberDecorate| for the group will be killed, but not the defining
  49. // |OpDecorationGroup| instruction.
  50. bool RemoveDecorationsFrom(
  51. uint32_t id, std::function<bool(const Instruction&)> pred =
  52. [](const Instruction&) { return true; });
  53. // Removes all decorations from the result id of |inst|.
  54. //
  55. // NOTE: This is only meant to be called from ir_context, as only metadata
  56. // will be removed, and no actual instruction.
  57. void RemoveDecoration(Instruction* inst);
  58. // Returns a vector of all decorations affecting |id|. If a group is applied
  59. // to |id|, the decorations of that group are returned rather than the group
  60. // decoration instruction. If |include_linkage| is not set, linkage
  61. // decorations won't be returned.
  62. std::vector<Instruction*> GetDecorationsFor(uint32_t id,
  63. bool include_linkage);
  64. std::vector<const Instruction*> GetDecorationsFor(uint32_t id,
  65. bool include_linkage) const;
  66. // Returns whether two IDs have the same decorations. Two
  67. // spv::Op::OpGroupDecorate instructions that apply the same decorations but
  68. // to different IDs, still count as being the same.
  69. bool HaveTheSameDecorations(uint32_t id1, uint32_t id2) const;
  70. // Returns whether two IDs have the same decorations. Two
  71. // spv::Op::OpGroupDecorate instructions that apply the same decorations but
  72. // to different IDs, still count as being the same.
  73. bool HaveSubsetOfDecorations(uint32_t id1, uint32_t id2) const;
  74. // Returns whether the two decorations instructions are the same and are
  75. // applying the same decorations; unless |ignore_target| is false, the targets
  76. // to which they are applied to does not matter, except for the member part.
  77. //
  78. // This is only valid for OpDecorate, OpMemberDecorate and OpDecorateId; it
  79. // will return false for other opcodes.
  80. bool AreDecorationsTheSame(const Instruction* inst1, const Instruction* inst2,
  81. bool ignore_target) const;
  82. // Returns whether a decoration instruction for |id| with decoration
  83. // |decoration| exists or not.
  84. bool HasDecoration(uint32_t id, uint32_t decoration) const;
  85. bool HasDecoration(uint32_t id, spv::Decoration decoration) const;
  86. // |f| is run on each decoration instruction for |id| with decoration
  87. // |decoration|. Processed are all decorations which target |id| either
  88. // directly or indirectly by Decoration Groups.
  89. void ForEachDecoration(uint32_t id, uint32_t decoration,
  90. std::function<void(const Instruction&)> f) const;
  91. // |f| is run on each decoration instruction for |id| with decoration
  92. // |decoration|. Processes all decoration which target |id| either directly or
  93. // indirectly through decoration groups. If |f| returns false, iteration is
  94. // terminated and this function returns false.
  95. bool WhileEachDecoration(uint32_t id, uint32_t decoration,
  96. std::function<bool(const Instruction&)> f) const;
  97. // |f| is run on each decoration instruction for |id| with decoration
  98. // |decoration|. Processes all decoration which target |id| either directly or
  99. // indirectly through decoration groups. If |f| returns true, iteration is
  100. // terminated and this function returns true. Otherwise returns false.
  101. bool FindDecoration(uint32_t id, uint32_t decoration,
  102. std::function<bool(const Instruction&)> f);
  103. // Clone all decorations from one id |from|.
  104. // The cloned decorations are assigned to the given id |to| and are
  105. // added to the module. The purpose is to decorate cloned instructions.
  106. // This function does not check if the id |to| is already decorated.
  107. void CloneDecorations(uint32_t from, uint32_t to);
  108. // Same as above, but only clone the decoration if the decoration operand is
  109. // in |decorations_to_copy|. This function has the extra restriction that
  110. // |from| and |to| must not be an object, not a type.
  111. void CloneDecorations(
  112. uint32_t from, uint32_t to,
  113. const std::vector<spv::Decoration>& decorations_to_copy);
  114. // Informs the decoration manager of a new decoration that it needs to track.
  115. void AddDecoration(Instruction* inst);
  116. // Add decoration with |opcode| and operands |opnds|.
  117. void AddDecoration(spv::Op opcode, const std::vector<Operand> opnds);
  118. // Add |decoration| of |inst_id| to module.
  119. void AddDecoration(uint32_t inst_id, uint32_t decoration);
  120. // Add |decoration, decoration_value| of |inst_id| to module.
  121. void AddDecorationVal(uint32_t inst_id, uint32_t decoration,
  122. uint32_t decoration_value);
  123. // Add |decoration, decoration_value| of |inst_id, member| to module.
  124. void AddMemberDecoration(uint32_t inst_id, uint32_t member,
  125. uint32_t decoration, uint32_t decoration_value);
  126. friend bool operator==(const DecorationManager&, const DecorationManager&);
  127. friend bool operator!=(const DecorationManager& lhs,
  128. const DecorationManager& rhs) {
  129. return !(lhs == rhs);
  130. }
  131. private:
  132. // Analyzes the defs and uses in the given |module| and populates data
  133. // structures in this class. Does nothing if |module| is nullptr.
  134. void AnalyzeDecorations();
  135. template <typename T>
  136. std::vector<T> InternalGetDecorationsFor(uint32_t id, bool include_linkage);
  137. // Tracks decoration information of an ID.
  138. struct TargetData {
  139. std::vector<Instruction*> direct_decorations; // All decorate
  140. // instructions applied
  141. // to the tracked ID.
  142. std::vector<Instruction*> indirect_decorations; // All instructions
  143. // applying a group to
  144. // the tracked ID.
  145. std::vector<Instruction*> decorate_insts; // All decorate instructions
  146. // applying the decorations
  147. // of the tracked ID to
  148. // targets.
  149. // It is empty if the
  150. // tracked ID is not a
  151. // group.
  152. };
  153. friend bool operator==(const TargetData& lhs, const TargetData& rhs) {
  154. if (!std::is_permutation(lhs.direct_decorations.begin(),
  155. lhs.direct_decorations.end(),
  156. rhs.direct_decorations.begin())) {
  157. return false;
  158. }
  159. if (!std::is_permutation(lhs.indirect_decorations.begin(),
  160. lhs.indirect_decorations.end(),
  161. rhs.indirect_decorations.begin())) {
  162. return false;
  163. }
  164. if (!std::is_permutation(lhs.decorate_insts.begin(),
  165. lhs.decorate_insts.end(),
  166. rhs.decorate_insts.begin())) {
  167. return false;
  168. }
  169. return true;
  170. }
  171. // Mapping from ids to the instructions applying a decoration to those ids.
  172. // In other words, for each id you get all decoration instructions
  173. // referencing that id, be it directly (spv::Op::OpDecorate,
  174. // spv::Op::OpMemberDecorate and spv::Op::OpDecorateId), or indirectly
  175. // (spv::Op::OpGroupDecorate, spv::Op::OpMemberGroupDecorate).
  176. std::unordered_map<uint32_t, TargetData> id_to_decoration_insts_;
  177. // The enclosing module.
  178. Module* module_;
  179. };
  180. } // namespace analysis
  181. } // namespace opt
  182. } // namespace spvtools
  183. #endif // SOURCE_OPT_DECORATION_MANAGER_H_