| 1558 | } |
| 1559 | |
| 1560 | opt::Instruction* GetLastInsertBeforeInstruction(opt::IRContext* ir_context, |
| 1561 | uint32_t block_id, |
| 1562 | spv::Op opcode) { |
| 1563 | // CFG::block uses std::map::at which throws an exception when |block_id| is |
| 1564 | // invalid. The error message is unhelpful, though. Thus, we test that |
| 1565 | // |block_id| is valid here. |
| 1566 | const auto* label_inst = ir_context->get_def_use_mgr()->GetDef(block_id); |
| 1567 | (void)label_inst; // Make compilers happy in release mode. |
| 1568 | assert(label_inst && label_inst->opcode() == spv::Op::OpLabel && |
| 1569 | "|block_id| is invalid"); |
| 1570 | |
| 1571 | auto* block = ir_context->cfg()->block(block_id); |
| 1572 | auto it = block->rbegin(); |
| 1573 | assert(it != block->rend() && "Basic block can't be empty"); |
| 1574 | |
| 1575 | if (block->GetMergeInst()) { |
| 1576 | ++it; |
| 1577 | assert(it != block->rend() && |
| 1578 | "|block| must have at least two instructions:" |
| 1579 | "terminator and a merge instruction"); |
| 1580 | } |
| 1581 | |
| 1582 | return CanInsertOpcodeBeforeInstruction(opcode, &*it) ? &*it : nullptr; |
| 1583 | } |
| 1584 | |
| 1585 | bool IdUseCanBeReplaced(opt::IRContext* ir_context, |
| 1586 | const TransformationContext& transformation_context, |
no test coverage detected