mem_pass.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. // Copyright (c) 2017 The Khronos Group Inc.
  2. // Copyright (c) 2017 Valve Corporation
  3. // Copyright (c) 2017 LunarG Inc.
  4. //
  5. // Licensed under the Apache License, Version 2.0 (the "License");
  6. // you may not use this file except in compliance with the License.
  7. // You may obtain a copy of the License at
  8. //
  9. // http://www.apache.org/licenses/LICENSE-2.0
  10. //
  11. // Unless required by applicable law or agreed to in writing, software
  12. // distributed under the License is distributed on an "AS IS" BASIS,
  13. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. // See the License for the specific language governing permissions and
  15. // limitations under the License.
  16. #ifndef SOURCE_OPT_MEM_PASS_H_
  17. #define SOURCE_OPT_MEM_PASS_H_
  18. #include <algorithm>
  19. #include <list>
  20. #include <map>
  21. #include <queue>
  22. #include <unordered_map>
  23. #include <unordered_set>
  24. #include <utility>
  25. #include "source/opt/basic_block.h"
  26. #include "source/opt/def_use_manager.h"
  27. #include "source/opt/dominator_analysis.h"
  28. #include "source/opt/module.h"
  29. #include "source/opt/pass.h"
  30. namespace spvtools {
  31. namespace opt {
  32. // A common base class for mem2reg-type passes. Provides common
  33. // utility functions and supporting state.
  34. class MemPass : public Pass {
  35. public:
  36. virtual ~MemPass() override = default;
  37. // Returns an undef value for the given |var_id|'s type.
  38. uint32_t GetUndefVal(uint32_t var_id) {
  39. return Type2Undef(GetPointeeTypeId(get_def_use_mgr()->GetDef(var_id)));
  40. }
  41. // Given a load or store |ip|, return the pointer instruction.
  42. // Also return the base variable's id in |varId|. If no base variable is
  43. // found, |varId| will be 0.
  44. Instruction* GetPtr(Instruction* ip, uint32_t* varId);
  45. // Return true if |varId| is a previously identified target variable.
  46. // Return false if |varId| is a previously identified non-target variable.
  47. //
  48. // Non-target variables are variable of function scope of a target type that
  49. // are accessed with constant-index access chains. not accessed with
  50. // non-constant-index access chains. Also cache non-target variables.
  51. //
  52. // If variable is not cached, return true if variable is a function scope
  53. // variable of target type, false otherwise. Updates caches of target and
  54. // non-target variables.
  55. bool IsTargetVar(uint32_t varId);
  56. // Collect target SSA variables. This traverses all the loads and stores in
  57. // function |func| looking for variables that can be replaced with SSA IDs. It
  58. // populates the sets |seen_target_vars_| and |seen_non_target_vars_|.
  59. void CollectTargetVars(Function* func);
  60. protected:
  61. MemPass();
  62. // Returns true if |typeInst| is a scalar type
  63. // or a vector or matrix
  64. bool IsBaseTargetType(const Instruction* typeInst) const;
  65. // Returns true if |typeInst| is a math type or a struct or array
  66. // of a math type.
  67. // TODO(): Add more complex types to convert
  68. bool IsTargetType(const Instruction* typeInst) const;
  69. // Returns true if |opcode| is a non-ptr access chain op
  70. bool IsNonPtrAccessChain(const spv::Op opcode) const;
  71. // Given the id |ptrId|, return true if the top-most non-CopyObj is
  72. // a variable, a non-ptr access chain or a parameter of pointer type.
  73. bool IsPtr(uint32_t ptrId);
  74. // Given the id of a pointer |ptrId|, return the top-most non-CopyObj.
  75. // Also return the base variable's id in |varId|. If no base variable is
  76. // found, |varId| will be 0.
  77. Instruction* GetPtr(uint32_t ptrId, uint32_t* varId);
  78. // Return true if all uses of |id| are only name or decorate ops.
  79. bool HasOnlyNamesAndDecorates(uint32_t id) const;
  80. // Kill all instructions in block |bp|. Whether or not to kill the label is
  81. // indicated by |killLabel|.
  82. void KillAllInsts(BasicBlock* bp, bool killLabel = true);
  83. // Return true if any instruction loads from |varId|
  84. bool HasLoads(uint32_t varId) const;
  85. // Return true if |varId| is not a function variable or if it has
  86. // a load
  87. bool IsLiveVar(uint32_t varId) const;
  88. // Add stores using |ptr_id| to |insts|
  89. void AddStores(uint32_t ptr_id, std::queue<Instruction*>* insts);
  90. // Delete |inst| and iterate DCE on all its operands if they are now
  91. // useless. If a load is deleted and its variable has no other loads,
  92. // delete all its variable's stores.
  93. void DCEInst(Instruction* inst, const std::function<void(Instruction*)>&);
  94. // Call all the cleanup helper functions on |func|.
  95. bool CFGCleanup(Function* func);
  96. // Return true if |op| is supported decorate.
  97. inline bool IsNonTypeDecorate(spv::Op op) const {
  98. return (op == spv::Op::OpDecorate || op == spv::Op::OpDecorateId);
  99. }
  100. // Return the id of an undef value with type |type_id|. Create and insert an
  101. // undef after the first non-variable in the function if it doesn't already
  102. // exist. Add undef to function undef map. Returns 0 of the value does not
  103. // exist, and cannot be created.
  104. uint32_t Type2Undef(uint32_t type_id);
  105. // Cache of verified target vars
  106. std::unordered_set<uint32_t> seen_target_vars_;
  107. // Cache of verified non-target vars
  108. std::unordered_set<uint32_t> seen_non_target_vars_;
  109. private:
  110. // Return true if all uses of |varId| are only through supported reference
  111. // operations ie. loads and store. Also cache in supported_ref_vars_.
  112. // TODO(dnovillo): This function is replicated in other passes and it's
  113. // slightly different in every pass. Is it possible to make one common
  114. // implementation?
  115. bool HasOnlySupportedRefs(uint32_t varId);
  116. // Remove all the unreachable basic blocks in |func|.
  117. bool RemoveUnreachableBlocks(Function* func);
  118. // Remove the block pointed by the iterator |*bi|. This also removes
  119. // all the instructions in the pointed-to block.
  120. void RemoveBlock(Function::iterator* bi);
  121. // Remove Phi operands in |phi| that are coming from blocks not in
  122. // |reachable_blocks|.
  123. void RemovePhiOperands(
  124. Instruction* phi,
  125. const std::unordered_set<BasicBlock*>& reachable_blocks);
  126. // Map from type to undef
  127. std::unordered_map<uint32_t, uint32_t> type2undefs_;
  128. };
  129. } // namespace opt
  130. } // namespace spvtools
  131. #endif // SOURCE_OPT_MEM_PASS_H_