| 23 | namespace opt { |
| 24 | |
| 25 | Pass::Status IfConversion::Process() { |
| 26 | if (!context()->get_feature_mgr()->HasCapability(spv::Capability::Shader)) { |
| 27 | return Status::SuccessWithoutChange; |
| 28 | } |
| 29 | |
| 30 | const ValueNumberTable& vn_table = *context()->GetValueNumberTable(); |
| 31 | bool modified = false; |
| 32 | std::vector<Instruction*> to_kill; |
| 33 | for (auto& func : *get_module()) { |
| 34 | DominatorAnalysis* dominators = context()->GetDominatorAnalysis(&func); |
| 35 | for (auto& block : func) { |
| 36 | // Check if it is possible for |block| to have phis that can be |
| 37 | // transformed. |
| 38 | BasicBlock* common = nullptr; |
| 39 | if (!CheckBlock(&block, dominators, &common)) continue; |
| 40 | |
| 41 | // Get an insertion point. |
| 42 | auto iter = block.begin(); |
| 43 | while (iter != block.end() && iter->opcode() == spv::Op::OpPhi) { |
| 44 | ++iter; |
| 45 | } |
| 46 | |
| 47 | InstructionBuilder builder( |
| 48 | context(), &*iter, |
| 49 | IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); |
| 50 | block.ForEachPhiInst([this, &builder, &modified, &common, &to_kill, |
| 51 | dominators, &block, &vn_table](Instruction* phi) { |
| 52 | // This phi is not compatible, but subsequent phis might be. |
| 53 | if (!CheckType(phi->type_id())) return; |
| 54 | |
| 55 | // We cannot transform cases where the phi is used by another phi in the |
| 56 | // same block due to instruction ordering restrictions. |
| 57 | // TODO(alan-baker): If all inappropriate uses could also be |
| 58 | // transformed, we could still remove this phi. |
| 59 | if (!CheckPhiUsers(phi, &block)) return; |
| 60 | |
| 61 | // Identify the incoming values associated with the true and false |
| 62 | // branches. If |then_block| dominates |inc0| or if the true edge |
| 63 | // branches straight to this block and |common| is |inc0|, then |inc0| |
| 64 | // is on the true branch. Otherwise the |inc1| is on the true branch. |
| 65 | BasicBlock* inc0 = GetIncomingBlock(phi, 0u); |
| 66 | Instruction* branch = common->terminator(); |
| 67 | uint32_t condition = branch->GetSingleWordInOperand(0u); |
| 68 | BasicBlock* then_block = GetBlock(branch->GetSingleWordInOperand(1u)); |
| 69 | Instruction* true_value = nullptr; |
| 70 | Instruction* false_value = nullptr; |
| 71 | if ((then_block == &block && inc0 == common) || |
| 72 | dominators->Dominates(then_block, inc0)) { |
| 73 | true_value = GetIncomingValue(phi, 0u); |
| 74 | false_value = GetIncomingValue(phi, 1u); |
| 75 | } else { |
| 76 | true_value = GetIncomingValue(phi, 1u); |
| 77 | false_value = GetIncomingValue(phi, 0u); |
| 78 | } |
| 79 | |
| 80 | BasicBlock* true_def_block = context()->get_instr_block(true_value); |
| 81 | BasicBlock* false_def_block = context()->get_instr_block(false_value); |
| 82 |
nothing calls this directly
no test coverage detected