def_use_manager.cpp 9.5 KB

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