| 617 | } |
| 618 | |
| 619 | BasicBlock* Loop::FindConditionBlock() const { |
| 620 | if (!loop_merge_) { |
| 621 | return nullptr; |
| 622 | } |
| 623 | BasicBlock* condition_block = nullptr; |
| 624 | |
| 625 | uint32_t in_loop_pred = 0; |
| 626 | for (uint32_t p : context_->cfg()->preds(loop_merge_->id())) { |
| 627 | if (IsInsideLoop(p)) { |
| 628 | if (in_loop_pred) { |
| 629 | // 2 in-loop predecessors. |
| 630 | return nullptr; |
| 631 | } |
| 632 | in_loop_pred = p; |
| 633 | } |
| 634 | } |
| 635 | if (!in_loop_pred) { |
| 636 | // Merge block is unreachable. |
| 637 | return nullptr; |
| 638 | } |
| 639 | |
| 640 | BasicBlock* bb = context_->cfg()->block(in_loop_pred); |
| 641 | |
| 642 | if (!bb) return nullptr; |
| 643 | |
| 644 | const Instruction& branch = *bb->ctail(); |
| 645 | |
| 646 | // Make sure the branch is a conditional branch. |
| 647 | if (branch.opcode() != spv::Op::OpBranchConditional) return nullptr; |
| 648 | |
| 649 | // Make sure one of the two possible branches is to the merge block. |
| 650 | if (branch.GetSingleWordInOperand(1) == loop_merge_->id() || |
| 651 | branch.GetSingleWordInOperand(2) == loop_merge_->id()) { |
| 652 | condition_block = bb; |
| 653 | } |
| 654 | |
| 655 | return condition_block; |
| 656 | } |
| 657 | |
| 658 | bool Loop::FindNumberOfIterations(const Instruction* induction, |
| 659 | const Instruction* branch_inst, |
no test coverage detected