MCPcopy Create free account
hub / github.com/KhronosGroup/SPIRV-Tools / TraverseUseDef

Method TraverseUseDef

source/opt/loop_fission.cpp:119–186  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

117}
118
119void LoopFissionImpl::TraverseUseDef(Instruction* inst,
120 std::set<Instruction*>* returned_set,
121 bool ignore_phi_users, bool report_loads) {
122 assert(returned_set && "Set to be returned cannot be null.");
123
124 analysis::DefUseManager* def_use = context_->get_def_use_mgr();
125 std::set<Instruction*>& inst_set = *returned_set;
126
127 // We create this functor to traverse the use def chain to build the
128 // grouping of related instructions. The lambda captures the std::function
129 // to allow it to recurse.
130 std::function<void(Instruction*)> traverser_functor;
131 traverser_functor = [this, def_use, &inst_set, &traverser_functor,
132 ignore_phi_users, report_loads](Instruction* user) {
133 // If we've seen the instruction before or it is not inside the loop end the
134 // traversal.
135 if (!user || seen_instructions_.count(user) != 0 ||
136 !context_->get_instr_block(user) ||
137 !loop_->IsInsideLoop(context_->get_instr_block(user))) {
138 return;
139 }
140
141 // Don't include labels or loop merge instructions in the instruction sets.
142 // Including them would mean we group instructions related only by using the
143 // same labels (i.e phis). We already preempt the inclusion of
144 // OpSelectionMerge by adding related instructions to the seen_instructions_
145 // set.
146 if (user->opcode() == spv::Op::OpLoopMerge ||
147 user->opcode() == spv::Op::OpLabel)
148 return;
149
150 // If the |report_loads| flag is set, set the class field
151 // load_used_in_condition_ to false. This is used to check that none of the
152 // condition checks in the loop rely on loads.
153 if (user->opcode() == spv::Op::OpLoad && report_loads) {
154 load_used_in_condition_ = true;
155 }
156
157 // Add the instruction to the set of instructions already seen, this breaks
158 // recursion and allows us to ignore certain instructions.
159 seen_instructions_.insert(user);
160
161 inst_set.insert(user);
162
163 // Wrapper functor to traverse the operands of each instruction.
164 auto traverse_operand = [&traverser_functor, def_use](const uint32_t* id) {
165 traverser_functor(def_use->GetDef(*id));
166 };
167 user->ForEachInOperand(traverse_operand);
168
169 // For the first traversal we want to ignore the users of the phi.
170 if (ignore_phi_users && user->opcode() == spv::Op::OpPhi) return;
171
172 // Traverse each user with this lambda.
173 def_use->ForEachUser(user, traverser_functor);
174
175 // Wrapper functor for the use traversal.
176 auto traverse_use = [&traverser_functor](Instruction* use, uint32_t) {

Callers

nothing calls this directly

Calls 10

get_instr_blockMethod · 0.80
ForEachInOperandMethod · 0.80
ForEachUserMethod · 0.80
ForEachUseMethod · 0.80
get_def_use_mgrMethod · 0.45
countMethod · 0.45
IsInsideLoopMethod · 0.45
opcodeMethod · 0.45
insertMethod · 0.45
GetDefMethod · 0.45

Tested by

no test coverage detected