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

Method Apply

source/fuzz/fuzzer_pass_split_blocks.cpp:33–100  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

31 transformations, ignore_inapplicable_transformations) {}
32
33void FuzzerPassSplitBlocks::Apply() {
34 // Gather up pointers to all the blocks in the module. We are then able to
35 // iterate over these pointers and split the blocks to which they point;
36 // we cannot safely split blocks while we iterate through the module.
37 std::vector<opt::BasicBlock*> blocks;
38 for (auto& function : *GetIRContext()->module()) {
39 for (auto& block : function) {
40 blocks.push_back(&block);
41 }
42 }
43
44 // Now go through all the block pointers that were gathered.
45 for (auto& block : blocks) {
46 // Probabilistically decide whether to try to split this block.
47 if (!GetFuzzerContext()->ChoosePercentage(
48 GetFuzzerContext()->GetChanceOfSplittingBlock())) {
49 // We are not going to try to split this block.
50 continue;
51 }
52
53 // TODO(https://github.com/KhronosGroup/SPIRV-Tools/issues/2964): consider
54 // taking a simpler approach to identifying the instruction before which
55 // to split a block.
56
57 // We are going to try to split this block. We now need to choose where
58 // to split it. We describe the instruction before which we would like to
59 // split a block via an InstructionDescriptor, details of which are
60 // commented in the protobufs definition file.
61 std::vector<protobufs::InstructionDescriptor> instruction_descriptors;
62
63 // The initial base instruction is the block label.
64 uint32_t base = block->id();
65
66 // Counts the number of times we have seen each opcode since we reset the
67 // base instruction.
68 std::map<spv::Op, uint32_t> skip_count;
69
70 // Consider every instruction in the block. The label is excluded: it is
71 // only necessary to consider it as a base in case the first instruction
72 // in the block does not have a result id.
73 for (auto& inst : *block) {
74 if (inst.HasResultId()) {
75 // In the case that the instruction has a result id, we use the
76 // instruction as its own base, and clear the skip counts we have
77 // collected.
78 base = inst.result_id();
79 skip_count.clear();
80 }
81 const spv::Op opcode = inst.opcode();
82 instruction_descriptors.emplace_back(MakeInstructionDescriptor(
83 base, opcode, skip_count.count(opcode) ? skip_count.at(opcode) : 0));
84 if (!inst.HasResultId()) {
85 skip_count[opcode] =
86 skip_count.count(opcode) ? skip_count.at(opcode) + 1 : 1;
87 }
88 }
89 // Having identified all the places we might be able to split the block,
90 // we choose one of them.

Callers

nothing calls this directly

Calls 15

ChoosePercentageMethod · 0.80
HasResultIdMethod · 0.80
emplace_backMethod · 0.80
RandomIndexMethod · 0.80
GetFreshIdMethod · 0.80
moduleMethod · 0.45
push_backMethod · 0.45
idMethod · 0.45
result_idMethod · 0.45

Tested by

no test coverage detected