| 292 | } |
| 293 | |
| 294 | BasicBlock* InvocationInterlockPlacementPass::splitEdge(BasicBlock* block, |
| 295 | uint32_t succ_id) { |
| 296 | // Create a new block to replace the critical edge. |
| 297 | uint32_t new_id = context()->TakeNextId(); |
| 298 | if (new_id == 0) { |
| 299 | return nullptr; |
| 300 | } |
| 301 | auto new_succ_temp = MakeUnique<BasicBlock>( |
| 302 | MakeUnique<Instruction>(context(), spv::Op::OpLabel, 0, new_id, |
| 303 | std::initializer_list<Operand>{})); |
| 304 | auto* new_succ = new_succ_temp.get(); |
| 305 | |
| 306 | // Insert the new block into the function. |
| 307 | block->GetParent()->InsertBasicBlockAfter(std::move(new_succ_temp), block); |
| 308 | |
| 309 | new_succ->AddInstruction(MakeUnique<Instruction>( |
| 310 | context(), spv::Op::OpBranch, 0, 0, |
| 311 | std::initializer_list<Operand>{ |
| 312 | Operand(spv_operand_type_t::SPV_OPERAND_TYPE_ID, {succ_id})})); |
| 313 | |
| 314 | assert(block->tail()->opcode() == spv::Op::OpBranchConditional || |
| 315 | block->tail()->opcode() == spv::Op::OpSwitch); |
| 316 | |
| 317 | // Update the first branch to successor to instead branch to |
| 318 | // the new successor. If there are multiple edges, we arbitrarily choose the |
| 319 | // first time it appears in the list. The other edges to `succ_id` will have |
| 320 | // to be split by another call to `splitEdge`. |
| 321 | block->tail()->WhileEachInId([new_succ, succ_id](uint32_t* branch_id) { |
| 322 | if (*branch_id == succ_id) { |
| 323 | *branch_id = new_succ->id(); |
| 324 | return false; |
| 325 | } |
| 326 | return true; |
| 327 | }); |
| 328 | |
| 329 | return new_succ; |
| 330 | } |
| 331 | |
| 332 | Pass::Status InvocationInterlockPlacementPass::placeInstructionsForEdge( |
| 333 | BasicBlock* block, uint32_t next_id, BlockSet& inside, |
nothing calls this directly
no test coverage detected