def_use_manager.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  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. #include "source/opt/def_use_manager.h"
  15. #include <iostream>
  16. #include "source/opt/log.h"
  17. #include "source/opt/reflect.h"
  18. namespace spvtools {
  19. namespace opt {
  20. namespace analysis {
  21. void DefUseManager::AnalyzeInstDef(Instruction* inst) {
  22. const uint32_t def_id = inst->result_id();
  23. if (def_id != 0) {
  24. auto iter = id_to_def_.find(def_id);
  25. if (iter != id_to_def_.end()) {
  26. // Clear the original instruction that defining the same result id of the
  27. // new instruction.
  28. ClearInst(iter->second);
  29. }
  30. id_to_def_[def_id] = inst;
  31. } else {
  32. ClearInst(inst);
  33. }
  34. }
  35. void DefUseManager::AnalyzeInstUse(Instruction* inst) {
  36. // Create entry for the given instruction. Note that the instruction may
  37. // not have any in-operands. In such cases, we still need a entry for those
  38. // instructions so this manager knows it has seen the instruction later.
  39. auto* used_ids = &inst_to_used_ids_[inst];
  40. if (used_ids->size()) {
  41. EraseUseRecordsOfOperandIds(inst);
  42. used_ids = &inst_to_used_ids_[inst];
  43. }
  44. used_ids->clear(); // It might have existed before.
  45. for (uint32_t i = 0; i < inst->NumOperands(); ++i) {
  46. switch (inst->GetOperand(i).type) {
  47. // For any id type but result id type
  48. case SPV_OPERAND_TYPE_ID:
  49. case SPV_OPERAND_TYPE_TYPE_ID:
  50. case SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID:
  51. case SPV_OPERAND_TYPE_SCOPE_ID: {
  52. uint32_t use_id = inst->GetSingleWordOperand(i);
  53. Instruction* def = GetDef(use_id);
  54. if (!def) assert(false && "Definition is not registered.");
  55. id_to_users_.insert(UserEntry(def, inst));
  56. used_ids->push_back(use_id);
  57. } break;
  58. default:
  59. break;
  60. }
  61. }
  62. }
  63. void DefUseManager::AnalyzeInstDefUse(Instruction* inst) {
  64. AnalyzeInstDef(inst);
  65. AnalyzeInstUse(inst);
  66. // Analyze lines last otherwise they will be cleared when inst is
  67. // cleared by preceding two calls
  68. for (auto& l_inst : inst->dbg_line_insts()) AnalyzeInstDefUse(&l_inst);
  69. }
  70. void DefUseManager::UpdateDefUse(Instruction* inst) {
  71. const uint32_t def_id = inst->result_id();
  72. if (def_id != 0) {
  73. auto iter = id_to_def_.find(def_id);
  74. if (iter == id_to_def_.end()) {
  75. AnalyzeInstDef(inst);
  76. }
  77. }
  78. AnalyzeInstUse(inst);
  79. }
  80. Instruction* DefUseManager::GetDef(uint32_t id) {
  81. auto iter = id_to_def_.find(id);
  82. if (iter == id_to_def_.end()) return nullptr;
  83. return iter->second;
  84. }
  85. const Instruction* DefUseManager::GetDef(uint32_t id) const {
  86. const auto iter = id_to_def_.find(id);
  87. if (iter == id_to_def_.end()) return nullptr;
  88. return iter->second;
  89. }
  90. DefUseManager::IdToUsersMap::const_iterator DefUseManager::UsersBegin(
  91. const Instruction* def) const {
  92. return id_to_users_.lower_bound(
  93. UserEntry(const_cast<Instruction*>(def), nullptr));
  94. }
  95. bool DefUseManager::UsersNotEnd(const IdToUsersMap::const_iterator& iter,
  96. const IdToUsersMap::const_iterator& cached_end,
  97. const Instruction* inst) const {
  98. return (iter != cached_end && iter->first == inst);
  99. }
  100. bool DefUseManager::UsersNotEnd(const IdToUsersMap::const_iterator& iter,
  101. const Instruction* inst) const {
  102. return UsersNotEnd(iter, id_to_users_.end(), inst);
  103. }
  104. bool DefUseManager::WhileEachUser(
  105. const Instruction* def, const std::function<bool(Instruction*)>& f) const {
  106. // Ensure that |def| has been registered.
  107. assert(def && (!def->HasResultId() || def == GetDef(def->result_id())) &&
  108. "Definition is not registered.");
  109. if (!def->HasResultId()) return true;
  110. auto end = id_to_users_.end();
  111. for (auto iter = UsersBegin(def); UsersNotEnd(iter, end, def); ++iter) {
  112. if (!f(iter->second)) return false;
  113. }
  114. return true;
  115. }
  116. bool DefUseManager::WhileEachUser(
  117. uint32_t id, const std::function<bool(Instruction*)>& f) const {
  118. return WhileEachUser(GetDef(id), f);
  119. }
  120. void DefUseManager::ForEachUser(
  121. const Instruction* def, const std::function<void(Instruction*)>& f) const {
  122. WhileEachUser(def, [&f](Instruction* user) {
  123. f(user);
  124. return true;
  125. });
  126. }
  127. void DefUseManager::ForEachUser(
  128. uint32_t id, const std::function<void(Instruction*)>& f) const {
  129. ForEachUser(GetDef(id), f);
  130. }
  131. bool DefUseManager::WhileEachUse(
  132. const Instruction* def,
  133. const std::function<bool(Instruction*, uint32_t)>& f) const {
  134. // Ensure that |def| has been registered.
  135. assert(def && (!def->HasResultId() || def == GetDef(def->result_id())) &&
  136. "Definition is not registered.");
  137. if (!def->HasResultId()) return true;
  138. auto end = id_to_users_.end();
  139. for (auto iter = UsersBegin(def); UsersNotEnd(iter, end, def); ++iter) {
  140. Instruction* user = iter->second;
  141. for (uint32_t idx = 0; idx != user->NumOperands(); ++idx) {
  142. const Operand& op = user->GetOperand(idx);
  143. if (op.type != SPV_OPERAND_TYPE_RESULT_ID && spvIsIdType(op.type)) {
  144. if (def->result_id() == op.words[0]) {
  145. if (!f(user, idx)) return false;
  146. }
  147. }
  148. }
  149. }
  150. return true;
  151. }
  152. bool DefUseManager::WhileEachUse(
  153. uint32_t id, const std::function<bool(Instruction*, uint32_t)>& f) const {
  154. return WhileEachUse(GetDef(id), f);
  155. }
  156. void DefUseManager::ForEachUse(
  157. const Instruction* def,
  158. const std::function<void(Instruction*, uint32_t)>& f) const {
  159. WhileEachUse(def, [&f](Instruction* user, uint32_t index) {
  160. f(user, index);
  161. return true;
  162. });
  163. }
  164. void DefUseManager::ForEachUse(
  165. uint32_t id, const std::function<void(Instruction*, uint32_t)>& f) const {
  166. ForEachUse(GetDef(id), f);
  167. }
  168. uint32_t DefUseManager::NumUsers(const Instruction* def) const {
  169. uint32_t count = 0;
  170. ForEachUser(def, [&count](Instruction*) { ++count; });
  171. return count;
  172. }
  173. uint32_t DefUseManager::NumUsers(uint32_t id) const {
  174. return NumUsers(GetDef(id));
  175. }
  176. uint32_t DefUseManager::NumUses(const Instruction* def) const {
  177. uint32_t count = 0;
  178. ForEachUse(def, [&count](Instruction*, uint32_t) { ++count; });
  179. return count;
  180. }
  181. uint32_t DefUseManager::NumUses(uint32_t id) const {
  182. return NumUses(GetDef(id));
  183. }
  184. std::vector<Instruction*> DefUseManager::GetAnnotations(uint32_t id) const {
  185. std::vector<Instruction*> annos;
  186. const Instruction* def = GetDef(id);
  187. if (!def) return annos;
  188. ForEachUser(def, [&annos](Instruction* user) {
  189. if (IsAnnotationInst(user->opcode())) {
  190. annos.push_back(user);
  191. }
  192. });
  193. return annos;
  194. }
  195. void DefUseManager::AnalyzeDefUse(Module* module) {
  196. if (!module) return;
  197. // Analyze all the defs before any uses to catch forward references.
  198. module->ForEachInst(
  199. std::bind(&DefUseManager::AnalyzeInstDef, this, std::placeholders::_1),
  200. true);
  201. module->ForEachInst(
  202. std::bind(&DefUseManager::AnalyzeInstUse, this, std::placeholders::_1),
  203. true);
  204. }
  205. void DefUseManager::ClearInst(Instruction* inst) {
  206. auto iter = inst_to_used_ids_.find(inst);
  207. if (iter != inst_to_used_ids_.end()) {
  208. EraseUseRecordsOfOperandIds(inst);
  209. if (inst->result_id() != 0) {
  210. // Remove all uses of this inst.
  211. auto users_begin = UsersBegin(inst);
  212. auto end = id_to_users_.end();
  213. auto new_end = users_begin;
  214. for (; UsersNotEnd(new_end, end, inst); ++new_end) {
  215. }
  216. id_to_users_.erase(users_begin, new_end);
  217. id_to_def_.erase(inst->result_id());
  218. }
  219. }
  220. }
  221. void DefUseManager::EraseUseRecordsOfOperandIds(const Instruction* inst) {
  222. // Go through all ids used by this instruction, remove this instruction's
  223. // uses of them.
  224. auto iter = inst_to_used_ids_.find(inst);
  225. if (iter != inst_to_used_ids_.end()) {
  226. for (auto use_id : iter->second) {
  227. id_to_users_.erase(
  228. UserEntry(GetDef(use_id), const_cast<Instruction*>(inst)));
  229. }
  230. inst_to_used_ids_.erase(inst);
  231. }
  232. }
  233. bool operator==(const DefUseManager& lhs, const DefUseManager& rhs) {
  234. if (lhs.id_to_def_ != rhs.id_to_def_) {
  235. for (auto p : lhs.id_to_def_) {
  236. if (rhs.id_to_def_.find(p.first) == rhs.id_to_def_.end()) {
  237. return false;
  238. }
  239. }
  240. for (auto p : rhs.id_to_def_) {
  241. if (lhs.id_to_def_.find(p.first) == lhs.id_to_def_.end()) {
  242. return false;
  243. }
  244. }
  245. return false;
  246. }
  247. if (lhs.id_to_users_ != rhs.id_to_users_) {
  248. for (auto p : lhs.id_to_users_) {
  249. if (rhs.id_to_users_.count(p) == 0) {
  250. return false;
  251. }
  252. }
  253. for (auto p : rhs.id_to_users_) {
  254. if (lhs.id_to_users_.count(p) == 0) {
  255. return false;
  256. }
  257. }
  258. return false;
  259. }
  260. if (lhs.inst_to_used_ids_ != rhs.inst_to_used_ids_) {
  261. for (auto p : lhs.inst_to_used_ids_) {
  262. if (rhs.inst_to_used_ids_.count(p.first) == 0) {
  263. return false;
  264. }
  265. }
  266. for (auto p : rhs.inst_to_used_ids_) {
  267. if (lhs.inst_to_used_ids_.count(p.first) == 0) {
  268. return false;
  269. }
  270. }
  271. return false;
  272. }
  273. return true;
  274. }
  275. } // namespace analysis
  276. } // namespace opt
  277. } // namespace spvtools