Unswitches |loop_|.
| 140 | |
| 141 | // Unswitches |loop_|. |
| 142 | bool PerformUnswitch() { |
| 143 | assert(CanUnswitchLoop() && |
| 144 | "Cannot unswitch if there is not constant condition"); |
| 145 | assert(loop_->GetPreHeaderBlock() && "This loop has no pre-header block"); |
| 146 | assert(loop_->IsLCSSA() && "This loop is not in LCSSA form"); |
| 147 | |
| 148 | CFG& cfg = *context_->cfg(); |
| 149 | DominatorTree* dom_tree = |
| 150 | &context_->GetDominatorAnalysis(function_)->GetDomTree(); |
| 151 | analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); |
| 152 | LoopUtils loop_utils(context_, loop_); |
| 153 | |
| 154 | ////////////////////////////////////////////////////////////////////////////// |
| 155 | // Step 1: Create the if merge block for structured modules. |
| 156 | // To do so, the |loop_| merge block will become the if's one and we |
| 157 | // create a merge for the loop. This will limit the amount of duplicated |
| 158 | // code the structured control flow imposes. |
| 159 | // For non structured program, the new loop will be connected to |
| 160 | // the old loop's exit blocks. |
| 161 | ////////////////////////////////////////////////////////////////////////////// |
| 162 | |
| 163 | // Get the merge block if it exists. |
| 164 | BasicBlock* if_merge_block = loop_->GetMergeBlock(); |
| 165 | // The merge block is only created if the loop has a unique exit block. We |
| 166 | // have this guarantee for structured loops, for compute loop it will |
| 167 | // trivially help maintain both a structured-like form and LCSAA. |
| 168 | BasicBlock* loop_merge_block = |
| 169 | if_merge_block |
| 170 | ? CreateBasicBlock(FindBasicBlockPosition(if_merge_block)) |
| 171 | : nullptr; |
| 172 | if (if_merge_block && !loop_merge_block) { |
| 173 | return false; |
| 174 | } |
| 175 | if (loop_merge_block) { |
| 176 | // Add the instruction and update managers. |
| 177 | InstructionBuilder builder( |
| 178 | context_, loop_merge_block, |
| 179 | IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping); |
| 180 | builder.AddBranch(if_merge_block->id()); |
| 181 | builder.SetInsertPoint(&*loop_merge_block->begin()); |
| 182 | cfg.RegisterBlock(loop_merge_block); |
| 183 | def_use_mgr->AnalyzeInstDef(loop_merge_block->GetLabelInst()); |
| 184 | bool ok = true; |
| 185 | if_merge_block->ForEachPhiInst( |
| 186 | [loop_merge_block, &ok, &builder, this](Instruction* phi) -> bool { |
| 187 | Instruction* cloned = phi->Clone(context_); |
| 188 | uint32_t new_id = TakeNextId(); |
| 189 | if (new_id == 0) { |
| 190 | ok = false; |
| 191 | return false; |
| 192 | } |
| 193 | cloned->SetResultId(new_id); |
| 194 | builder.AddInstruction(std::unique_ptr<Instruction>(cloned)); |
| 195 | phi->SetInOperand(0, {cloned->result_id()}); |
| 196 | phi->SetInOperand(1, {loop_merge_block->id()}); |
| 197 | for (uint32_t j = phi->NumInOperands() - 1; j > 1; j--) |
| 198 | phi->RemoveInOperand(j); |
| 199 | return true; |
no test coverage detected