value_number_table.cpp 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. // Copyright (c) 2017 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/value_number_table.h"
  15. #include <algorithm>
  16. #include "source/opt/cfg.h"
  17. #include "source/opt/ir_context.h"
  18. namespace spvtools {
  19. namespace opt {
  20. uint32_t ValueNumberTable::GetValueNumber(Instruction* inst) const {
  21. assert(inst->result_id() != 0 &&
  22. "inst must have a result id to get a value number.");
  23. // Check if this instruction already has a value.
  24. auto result_id_to_val = id_to_value_.find(inst->result_id());
  25. if (result_id_to_val != id_to_value_.end()) {
  26. return result_id_to_val->second;
  27. }
  28. return 0;
  29. }
  30. uint32_t ValueNumberTable::GetValueNumber(uint32_t id) const {
  31. return GetValueNumber(context()->get_def_use_mgr()->GetDef(id));
  32. }
  33. uint32_t ValueNumberTable::AssignValueNumber(Instruction* inst) {
  34. // If it already has a value return that.
  35. uint32_t value = GetValueNumber(inst);
  36. if (value != 0) {
  37. return value;
  38. }
  39. // If the instruction has other side effects, then it must
  40. // have its own value number.
  41. // OpSampledImage and OpImage must remain in the same basic block in which
  42. // they are used, because of this we will assign each one it own value number.
  43. if (!context()->IsCombinatorInstruction(inst) &&
  44. !inst->IsCommonDebugInstr()) {
  45. value = TakeNextValueNumber();
  46. id_to_value_[inst->result_id()] = value;
  47. return value;
  48. }
  49. switch (inst->opcode()) {
  50. case spv::Op::OpSampledImage:
  51. case spv::Op::OpImage:
  52. case spv::Op::OpVariable:
  53. value = TakeNextValueNumber();
  54. id_to_value_[inst->result_id()] = value;
  55. return value;
  56. default:
  57. break;
  58. }
  59. // If it is a load from memory that can be modified, we have to assume the
  60. // memory has been modified, so we give it a new value number.
  61. //
  62. // Note that this test will also handle volatile loads because they are not
  63. // read only. However, if this is ever relaxed because we analyze stores, we
  64. // will have to add a new case for volatile loads.
  65. if (inst->IsLoad() && !inst->IsReadOnlyLoad()) {
  66. value = TakeNextValueNumber();
  67. id_to_value_[inst->result_id()] = value;
  68. return value;
  69. }
  70. analysis::DecorationManager* dec_mgr = context()->get_decoration_mgr();
  71. // When we copy an object, the value numbers should be the same.
  72. if (inst->opcode() == spv::Op::OpCopyObject &&
  73. dec_mgr->HaveTheSameDecorations(inst->result_id(),
  74. inst->GetSingleWordInOperand(0))) {
  75. value = GetValueNumber(inst->GetSingleWordInOperand(0));
  76. if (value != 0) {
  77. id_to_value_[inst->result_id()] = value;
  78. return value;
  79. }
  80. }
  81. // Phi nodes are a type of copy. If all of the inputs have the same value
  82. // number, then we can assign the result of the phi the same value number.
  83. if (inst->opcode() == spv::Op::OpPhi && inst->NumInOperands() > 0 &&
  84. dec_mgr->HaveTheSameDecorations(inst->result_id(),
  85. inst->GetSingleWordInOperand(0))) {
  86. value = GetValueNumber(inst->GetSingleWordInOperand(0));
  87. if (value != 0) {
  88. for (uint32_t op = 2; op < inst->NumInOperands(); op += 2) {
  89. if (value != GetValueNumber(inst->GetSingleWordInOperand(op))) {
  90. value = 0;
  91. break;
  92. }
  93. }
  94. if (value != 0) {
  95. id_to_value_[inst->result_id()] = value;
  96. return value;
  97. }
  98. }
  99. }
  100. // Replace all of the operands by their value number. The sign bit will be
  101. // set to distinguish between an id and a value number.
  102. Instruction value_ins(context(), inst->opcode(), inst->type_id(),
  103. inst->result_id(), {});
  104. for (uint32_t o = 0; o < inst->NumInOperands(); ++o) {
  105. const Operand& op = inst->GetInOperand(o);
  106. if (spvIsIdType(op.type)) {
  107. uint32_t id_value = op.words[0];
  108. auto use_id_to_val = id_to_value_.find(id_value);
  109. if (use_id_to_val != id_to_value_.end()) {
  110. id_value = (1 << 31) | use_id_to_val->second;
  111. }
  112. value_ins.AddOperand(Operand(op.type, {id_value}));
  113. } else {
  114. value_ins.AddOperand(Operand(op.type, op.words));
  115. }
  116. }
  117. // TODO: Implement a normal form for opcodes that commute like integer
  118. // addition. This will let us know that a+b is the same value as b+a.
  119. // Otherwise, we check if this value has been computed before.
  120. auto value_iterator = instruction_to_value_.find(value_ins);
  121. if (value_iterator != instruction_to_value_.end()) {
  122. value = id_to_value_[value_iterator->first.result_id()];
  123. id_to_value_[inst->result_id()] = value;
  124. return value;
  125. }
  126. // If not, assign it a new value number.
  127. value = TakeNextValueNumber();
  128. id_to_value_[inst->result_id()] = value;
  129. instruction_to_value_[value_ins] = value;
  130. return value;
  131. }
  132. void ValueNumberTable::BuildDominatorTreeValueNumberTable() {
  133. // First value number the headers.
  134. for (auto& inst : context()->annotations()) {
  135. if (inst.result_id() != 0) {
  136. AssignValueNumber(&inst);
  137. }
  138. }
  139. for (auto& inst : context()->capabilities()) {
  140. if (inst.result_id() != 0) {
  141. AssignValueNumber(&inst);
  142. }
  143. }
  144. for (auto& inst : context()->types_values()) {
  145. if (inst.result_id() != 0) {
  146. AssignValueNumber(&inst);
  147. }
  148. }
  149. for (auto& inst : context()->module()->ext_inst_imports()) {
  150. if (inst.result_id() != 0) {
  151. AssignValueNumber(&inst);
  152. }
  153. }
  154. for (auto& inst : context()->module()->ext_inst_debuginfo()) {
  155. if (inst.result_id() != 0) {
  156. AssignValueNumber(&inst);
  157. }
  158. }
  159. for (Function& func : *context()->module()) {
  160. // For best results we want to traverse the code in reverse post order.
  161. // This happens naturally because of the forward referencing rules.
  162. for (BasicBlock& block : func) {
  163. for (Instruction& inst : block) {
  164. if (inst.result_id() != 0) {
  165. AssignValueNumber(&inst);
  166. }
  167. }
  168. }
  169. }
  170. }
  171. bool ComputeSameValue::operator()(const Instruction& lhs,
  172. const Instruction& rhs) const {
  173. if (lhs.result_id() == 0 || rhs.result_id() == 0) {
  174. return false;
  175. }
  176. if (lhs.opcode() != rhs.opcode()) {
  177. return false;
  178. }
  179. if (lhs.type_id() != rhs.type_id()) {
  180. return false;
  181. }
  182. if (lhs.NumInOperands() != rhs.NumInOperands()) {
  183. return false;
  184. }
  185. for (uint32_t i = 0; i < lhs.NumInOperands(); ++i) {
  186. if (lhs.GetInOperand(i) != rhs.GetInOperand(i)) {
  187. return false;
  188. }
  189. }
  190. return lhs.context()->get_decoration_mgr()->HaveTheSameDecorations(
  191. lhs.result_id(), rhs.result_id());
  192. }
  193. std::size_t ValueTableHash::operator()(const Instruction& inst) const {
  194. // We hash the opcode and in-operands, not the result, because we want
  195. // instructions that are the same except for the result to hash to the
  196. // same value.
  197. std::u32string h;
  198. h.push_back(uint32_t(inst.opcode()));
  199. h.push_back(inst.type_id());
  200. for (uint32_t i = 0; i < inst.NumInOperands(); ++i) {
  201. const auto& opnd = inst.GetInOperand(i);
  202. for (uint32_t word : opnd.words) {
  203. h.push_back(word);
  204. }
  205. }
  206. return std::hash<std::u32string>()(h);
  207. }
  208. } // namespace opt
  209. } // namespace spvtools