| 858 | } |
| 859 | |
| 860 | Instruction* Loop::FindConditionVariable( |
| 861 | const BasicBlock* condition_block) const { |
| 862 | // Find the branch instruction. |
| 863 | const Instruction& branch_inst = *condition_block->ctail(); |
| 864 | |
| 865 | Instruction* induction = nullptr; |
| 866 | // Verify that the branch instruction is a conditional branch. |
| 867 | if (branch_inst.opcode() == spv::Op::OpBranchConditional) { |
| 868 | // From the branch instruction find the branch condition. |
| 869 | analysis::DefUseManager* def_use_manager = context_->get_def_use_mgr(); |
| 870 | |
| 871 | // Find the instruction representing the condition used in the conditional |
| 872 | // branch. |
| 873 | Instruction* condition = |
| 874 | def_use_manager->GetDef(branch_inst.GetSingleWordOperand(0)); |
| 875 | |
| 876 | // Ensure that the condition is a less than operation. |
| 877 | if (condition && IsSupportedCondition(condition->opcode())) { |
| 878 | // The left hand side operand of the operation. |
| 879 | Instruction* variable_inst = |
| 880 | def_use_manager->GetDef(condition->GetSingleWordOperand(2)); |
| 881 | |
| 882 | // Make sure the variable instruction used is a phi. |
| 883 | if (!variable_inst || variable_inst->opcode() != spv::Op::OpPhi) |
| 884 | return nullptr; |
| 885 | |
| 886 | // Make sure the phi instruction only has two incoming blocks. Each |
| 887 | // incoming block will be represented by two in operands in the phi |
| 888 | // instruction, the value and the block which that value came from. We |
| 889 | // assume the cannocalised phi will have two incoming values, one from the |
| 890 | // preheader and one from the continue block. |
| 891 | size_t max_supported_operands = 4; |
| 892 | if (variable_inst->NumInOperands() == max_supported_operands) { |
| 893 | // The operand index of the first incoming block label. |
| 894 | uint32_t operand_label_1 = 1; |
| 895 | |
| 896 | // The operand index of the second incoming block label. |
| 897 | uint32_t operand_label_2 = 3; |
| 898 | |
| 899 | // Make sure one of them is the preheader. |
| 900 | if (!IsInsideLoop( |
| 901 | variable_inst->GetSingleWordInOperand(operand_label_1)) && |
| 902 | !IsInsideLoop( |
| 903 | variable_inst->GetSingleWordInOperand(operand_label_2))) { |
| 904 | return nullptr; |
| 905 | } |
| 906 | |
| 907 | // And make sure that the other is the latch block. |
| 908 | if (variable_inst->GetSingleWordInOperand(operand_label_1) != |
| 909 | loop_latch_->id() && |
| 910 | variable_inst->GetSingleWordInOperand(operand_label_2) != |
| 911 | loop_latch_->id()) { |
| 912 | return nullptr; |
| 913 | } |
| 914 | } else { |
| 915 | return nullptr; |
| 916 | } |
| 917 |
no test coverage detected