def_use_manager.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  1. // Copyright (c) 2016 Google Inc.
  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_DEF_USE_MANAGER_H_
  15. #define SOURCE_OPT_DEF_USE_MANAGER_H_
  16. #include <set>
  17. #include <unordered_map>
  18. #include <vector>
  19. #include "source/opt/instruction.h"
  20. #include "source/opt/module.h"
  21. #include "spirv-tools/libspirv.hpp"
  22. namespace spvtools {
  23. namespace opt {
  24. namespace analysis {
  25. // Definition should never be null. User can be null, however, such an entry
  26. // should be used only for searching (e.g. all users of a particular definition)
  27. // and never stored in a container.
  28. struct UserEntry {
  29. Instruction* def;
  30. Instruction* user;
  31. };
  32. inline bool operator==(const UserEntry& lhs, const UserEntry& rhs) {
  33. return lhs.def == rhs.def && lhs.user == rhs.user;
  34. }
  35. // Orders UserEntry for use in associative containers (i.e. less than ordering).
  36. //
  37. // The definition of an UserEntry is treated as the major key and the users as
  38. // the minor key so that all the users of a particular definition are
  39. // consecutive in a container.
  40. //
  41. // A null user always compares less than a real user. This is done to provide
  42. // easy values to search for the beginning of the users of a particular
  43. // definition (i.e. using {def, nullptr}).
  44. struct UserEntryLess {
  45. bool operator()(const UserEntry& lhs, const UserEntry& rhs) const {
  46. // If lhs.def and rhs.def are both null, fall through to checking the
  47. // second entries.
  48. if (!lhs.def && rhs.def) return true;
  49. if (lhs.def && !rhs.def) return false;
  50. // If neither definition is null, then compare unique ids.
  51. if (lhs.def && rhs.def) {
  52. if (lhs.def->unique_id() < rhs.def->unique_id()) return true;
  53. if (rhs.def->unique_id() < lhs.def->unique_id()) return false;
  54. }
  55. // Return false on equality.
  56. if (!lhs.user && !rhs.user) return false;
  57. if (!lhs.user) return true;
  58. if (!rhs.user) return false;
  59. // If neither user is null then compare unique ids.
  60. return lhs.user->unique_id() < rhs.user->unique_id();
  61. }
  62. };
  63. // A class for analyzing and managing defs and uses in an Module.
  64. class DefUseManager {
  65. public:
  66. using IdToDefMap = std::unordered_map<uint32_t, Instruction*>;
  67. // Constructs a def-use manager from the given |module|. All internal messages
  68. // will be communicated to the outside via the given message |consumer|. This
  69. // instance only keeps a reference to the |consumer|, so the |consumer| should
  70. // outlive this instance.
  71. DefUseManager(Module* module) { AnalyzeDefUse(module); }
  72. DefUseManager(const DefUseManager&) = delete;
  73. DefUseManager(DefUseManager&&) = delete;
  74. DefUseManager& operator=(const DefUseManager&) = delete;
  75. DefUseManager& operator=(DefUseManager&&) = delete;
  76. // Analyzes the defs in the given |inst|.
  77. void AnalyzeInstDef(Instruction* inst);
  78. // Analyzes the uses in the given |inst|.
  79. //
  80. // All operands of |inst| must be analyzed as defs.
  81. void AnalyzeInstUse(Instruction* inst);
  82. // Analyzes the defs and uses in the given |inst|.
  83. void AnalyzeInstDefUse(Instruction* inst);
  84. // Returns the def instruction for the given |id|. If there is no instruction
  85. // defining |id|, returns nullptr.
  86. Instruction* GetDef(uint32_t id);
  87. const Instruction* GetDef(uint32_t id) const;
  88. // Runs the given function |f| on each unique user instruction of |def| (or
  89. // |id|).
  90. //
  91. // If one instruction uses |def| in multiple operands, that instruction will
  92. // only be visited once.
  93. //
  94. // |def| (or |id|) must be registered as a definition.
  95. void ForEachUser(const Instruction* def,
  96. const std::function<void(Instruction*)>& f) const;
  97. void ForEachUser(uint32_t id,
  98. const std::function<void(Instruction*)>& f) const;
  99. // Runs the given function |f| on each unique user instruction of |def| (or
  100. // |id|). If |f| returns false, iteration is terminated and this function
  101. // returns false.
  102. //
  103. // If one instruction uses |def| in multiple operands, that instruction will
  104. // be only be visited once.
  105. //
  106. // |def| (or |id|) must be registered as a definition.
  107. bool WhileEachUser(const Instruction* def,
  108. const std::function<bool(Instruction*)>& f) const;
  109. bool WhileEachUser(uint32_t id,
  110. const std::function<bool(Instruction*)>& f) const;
  111. // Runs the given function |f| on each unique use of |def| (or
  112. // |id|).
  113. //
  114. // If one instruction uses |def| in multiple operands, each operand will be
  115. // visited separately.
  116. //
  117. // |def| (or |id|) must be registered as a definition.
  118. void ForEachUse(
  119. const Instruction* def,
  120. const std::function<void(Instruction*, uint32_t operand_index)>& f) const;
  121. void ForEachUse(
  122. uint32_t id,
  123. const std::function<void(Instruction*, uint32_t operand_index)>& f) const;
  124. // Runs the given function |f| on each unique use of |def| (or
  125. // |id|). If |f| returns false, iteration is terminated and this function
  126. // returns false.
  127. //
  128. // If one instruction uses |def| in multiple operands, each operand will be
  129. // visited separately.
  130. //
  131. // |def| (or |id|) must be registered as a definition.
  132. bool WhileEachUse(
  133. const Instruction* def,
  134. const std::function<bool(Instruction*, uint32_t operand_index)>& f) const;
  135. bool WhileEachUse(
  136. uint32_t id,
  137. const std::function<bool(Instruction*, uint32_t operand_index)>& f) const;
  138. // Returns the number of users of |def| (or |id|).
  139. uint32_t NumUsers(const Instruction* def) const;
  140. uint32_t NumUsers(uint32_t id) const;
  141. // Returns the number of uses of |def| (or |id|).
  142. uint32_t NumUses(const Instruction* def) const;
  143. uint32_t NumUses(uint32_t id) const;
  144. // Returns the annotation instrunctions which are a direct use of the given
  145. // |id|. This means when the decorations are applied through decoration
  146. // group(s), this function will just return the OpGroupDecorate
  147. // instruction(s) which refer to the given id as an operand. The OpDecorate
  148. // instructions which decorate the decoration group will not be returned.
  149. std::vector<Instruction*> GetAnnotations(uint32_t id) const;
  150. // Returns the map from ids to their def instructions.
  151. const IdToDefMap& id_to_defs() const { return id_to_def_; }
  152. // Clear the internal def-use record of the given instruction |inst|. This
  153. // method will update the use information of the operand ids of |inst|. The
  154. // record: |inst| uses an |id|, will be removed from the use records of |id|.
  155. // If |inst| defines an result id, the use record of this result id will also
  156. // be removed. Does nothing if |inst| was not analyzed before.
  157. void ClearInst(Instruction* inst);
  158. // Erases the records that a given instruction uses its operand ids.
  159. void EraseUseRecordsOfOperandIds(const Instruction* inst);
  160. friend bool CompareAndPrintDifferences(const DefUseManager&,
  161. const DefUseManager&);
  162. // If |inst| has not already been analysed, then analyses its definition and
  163. // uses.
  164. void UpdateDefUse(Instruction* inst);
  165. private:
  166. using IdToUsersMap = std::set<UserEntry, UserEntryLess>;
  167. using InstToUsedIdsMap =
  168. std::unordered_map<const Instruction*, std::vector<uint32_t>>;
  169. // Returns the first location that {|def|, nullptr} could be inserted into the
  170. // users map without violating ordering.
  171. IdToUsersMap::const_iterator UsersBegin(const Instruction* def) const;
  172. // Returns true if |iter| has not reached the end of |def|'s users.
  173. //
  174. // In the first version |iter| is compared against the end of the map for
  175. // validity before other checks. In the second version, |iter| is compared
  176. // against |cached_end| for validity before other checks. This allows caching
  177. // the map's end which is a performance improvement on some platforms.
  178. bool UsersNotEnd(const IdToUsersMap::const_iterator& iter,
  179. const Instruction* def) const;
  180. bool UsersNotEnd(const IdToUsersMap::const_iterator& iter,
  181. const IdToUsersMap::const_iterator& cached_end,
  182. const Instruction* def) const;
  183. // Analyzes the defs and uses in the given |module| and populates data
  184. // structures in this class. Does nothing if |module| is nullptr.
  185. void AnalyzeDefUse(Module* module);
  186. IdToDefMap id_to_def_; // Mapping from ids to their definitions
  187. IdToUsersMap id_to_users_; // Mapping from ids to their users
  188. // Mapping from instructions to the ids used in the instruction.
  189. InstToUsedIdsMap inst_to_used_ids_;
  190. };
  191. } // namespace analysis
  192. } // namespace opt
  193. } // namespace spvtools
  194. #endif // SOURCE_OPT_DEF_USE_MANAGER_H_