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

Method Apply

source/fuzz/transformation_split_block.cpp:91–151  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

89}
90
91void TransformationSplitBlock::Apply(
92 opt::IRContext* ir_context,
93 TransformationContext* transformation_context) const {
94 opt::Instruction* instruction_to_split_before =
95 FindInstruction(message_.instruction_to_split_before(), ir_context);
96 opt::BasicBlock* block_to_split =
97 ir_context->get_instr_block(instruction_to_split_before);
98 auto split_before = fuzzerutil::GetIteratorForInstruction(
99 block_to_split, instruction_to_split_before);
100 assert(split_before != block_to_split->end() &&
101 "If the transformation is applicable, we should have an "
102 "instruction to split on.");
103
104 // We need to make sure the module's id bound is large enough to add the
105 // fresh id.
106 fuzzerutil::UpdateModuleIdBound(ir_context, message_.fresh_id());
107 // Split the block.
108 auto new_bb = block_to_split->SplitBasicBlock(ir_context, message_.fresh_id(),
109 split_before);
110 // The split does not automatically add a branch between the two parts of
111 // the original block, so we add one.
112 auto branch_instruction = MakeUnique<opt::Instruction>(
113 ir_context, spv::Op::OpBranch, 0, 0,
114 std::initializer_list<opt::Operand>{opt::Operand(
115 spv_operand_type_t::SPV_OPERAND_TYPE_ID, {message_.fresh_id()})});
116 auto branch_instruction_ptr = branch_instruction.get();
117 block_to_split->AddInstruction(std::move(branch_instruction));
118
119 // Inform the def-use manager about the branch instruction, and record its
120 // block.
121 ir_context->get_def_use_mgr()->AnalyzeInstDefUse(branch_instruction_ptr);
122 ir_context->set_instr_block(branch_instruction_ptr, block_to_split);
123
124 // If we split before OpPhi instructions, we need to update their
125 // predecessor operand so that the block they used to be inside is now the
126 // predecessor.
127 new_bb->ForEachPhiInst([block_to_split,
128 ir_context](opt::Instruction* phi_inst) {
129 assert(
130 phi_inst->NumInOperands() == 2 &&
131 "Precondition: a block can only be split before an OpPhi if the block"
132 "has exactly one predecessor.");
133 phi_inst->SetInOperand(1, {block_to_split->id()});
134 ir_context->UpdateDefUse(phi_inst);
135 });
136
137 // We have updated the def-use manager and the instruction to block mapping,
138 // but other analyses (especially control flow-related ones) need to be
139 // recomputed.
140 ir_context->InvalidateAnalysesExceptFor(
141 opt::IRContext::Analysis::kAnalysisDefUse |
142 opt::IRContext::Analysis::kAnalysisInstrToBlockMapping);
143
144 // If the block being split was dead, the new block arising from the split is
145 // also dead.
146 if (transformation_context->GetFactManager()->BlockIsDead(
147 block_to_split->id())) {
148 transformation_context->GetFactManager()->AddFactBlockIsDead(

Callers

nothing calls this directly

Calls 15

FindInstructionFunction · 0.85
UpdateModuleIdBoundFunction · 0.85
get_instr_blockMethod · 0.80
SplitBasicBlockMethod · 0.80
getMethod · 0.80
AnalyzeInstDefUseMethod · 0.80
set_instr_blockMethod · 0.80
ForEachPhiInstMethod · 0.80
NumInOperandsMethod · 0.80
SetInOperandMethod · 0.80

Tested by

no test coverage detected