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

Method GroupInstructionsByUseDef

source/opt/loop_fission.cpp:188–267  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

186}
187
188bool LoopFissionImpl::GroupInstructionsByUseDef() {
189 std::vector<std::set<Instruction*>> sets{};
190
191 // We want to ignore all the instructions stemming from the loop condition
192 // instruction.
193 BasicBlock* condition_block = loop_->FindConditionBlock();
194
195 if (!condition_block) return false;
196 Instruction* condition = &*condition_block->tail();
197
198 // We iterate over the blocks via iterating over all the blocks in the
199 // function, we do this so we are iterating in the same order which the blocks
200 // appear in the binary.
201 Function& function = *loop_->GetHeaderBlock()->GetParent();
202
203 // Create a temporary set to ignore certain groups of instructions within the
204 // loop. We don't want any instructions related to control flow to be removed
205 // from either loop only instructions within the control flow bodies.
206 std::set<Instruction*> instructions_to_ignore{};
207 TraverseUseDef(condition, &instructions_to_ignore, true, true);
208
209 // Traverse control flow instructions to ensure they are added to the
210 // seen_instructions_ set and will be ignored when it it called with actual
211 // sets.
212 for (BasicBlock& block : function) {
213 if (!loop_->IsInsideLoop(block.id())) continue;
214
215 for (Instruction& inst : block) {
216 // Ignore all instructions related to control flow.
217 if (inst.opcode() == spv::Op::OpSelectionMerge || inst.IsBranch()) {
218 TraverseUseDef(&inst, &instructions_to_ignore, true, true);
219 }
220 }
221 }
222
223 // Traverse the instructions and generate the sets, automatically ignoring any
224 // instructions in instructions_to_ignore.
225 for (BasicBlock& block : function) {
226 if (!loop_->IsInsideLoop(block.id()) ||
227 loop_->GetHeaderBlock()->id() == block.id())
228 continue;
229
230 for (Instruction& inst : block) {
231 // Record the order that each load/store is seen.
232 if (inst.opcode() == spv::Op::OpLoad ||
233 inst.opcode() == spv::Op::OpStore) {
234 instruction_order_[&inst] = instruction_order_.size();
235 }
236
237 // Ignore instructions already seen in a traversal.
238 if (seen_instructions_.count(&inst) != 0) {
239 continue;
240 }
241
242 // Build the set.
243 std::set<Instruction*> inst_set{};
244 TraverseUseDef(&inst, &inst_set);
245 if (!inst_set.empty()) sets.push_back(std::move(inst_set));

Callers 1

ProcessMethod · 0.80

Calls 15

FindConditionBlockMethod · 0.80
IsBranchMethod · 0.80
tailMethod · 0.45
GetParentMethod · 0.45
GetHeaderBlockMethod · 0.45
IsInsideLoopMethod · 0.45
idMethod · 0.45
opcodeMethod · 0.45
sizeMethod · 0.45
countMethod · 0.45
emptyMethod · 0.45
push_backMethod · 0.45

Tested by

no test coverage detected