| 46 | size_t LoopPeelingPass::code_grow_threshold_ = 1000; |
| 47 | |
| 48 | bool LoopPeeling::DuplicateAndConnectLoop( |
| 49 | LoopUtils::LoopCloningResult* clone_results) { |
| 50 | CFG& cfg = *context_->cfg(); |
| 51 | analysis::DefUseManager* def_use_mgr = context_->get_def_use_mgr(); |
| 52 | |
| 53 | assert(CanPeelLoop() && "Cannot peel loop!"); |
| 54 | |
| 55 | std::vector<BasicBlock*> ordered_loop_blocks; |
| 56 | BasicBlock* pre_header = loop_->GetOrCreatePreHeaderBlock(); |
| 57 | if (!pre_header) { |
| 58 | return false; |
| 59 | } |
| 60 | |
| 61 | loop_->ComputeLoopStructuredOrder(&ordered_loop_blocks); |
| 62 | |
| 63 | cloned_loop_ = loop_utils_.CloneLoop(clone_results, ordered_loop_blocks); |
| 64 | if (!cloned_loop_) { |
| 65 | return false; |
| 66 | } |
| 67 | |
| 68 | // Add the basic block to the function. |
| 69 | Function::iterator it = |
| 70 | loop_utils_.GetFunction()->FindBlock(pre_header->id()); |
| 71 | assert(it != loop_utils_.GetFunction()->end() && |
| 72 | "Pre-header not found in the function."); |
| 73 | loop_utils_.GetFunction()->AddBasicBlocks( |
| 74 | clone_results->cloned_bb_.begin(), clone_results->cloned_bb_.end(), ++it); |
| 75 | |
| 76 | // Make the |loop_|'s preheader the |cloned_loop_| one. |
| 77 | BasicBlock* cloned_header = cloned_loop_->GetHeaderBlock(); |
| 78 | pre_header->ForEachSuccessorLabel( |
| 79 | [cloned_header](uint32_t* succ) { *succ = cloned_header->id(); }); |
| 80 | |
| 81 | // Update cfg. |
| 82 | cfg.RemoveEdge(pre_header->id(), loop_->GetHeaderBlock()->id()); |
| 83 | cloned_loop_->SetPreHeaderBlock(pre_header); |
| 84 | loop_->SetPreHeaderBlock(nullptr); |
| 85 | |
| 86 | // When cloning the loop, we didn't cloned the merge block, so currently |
| 87 | // |cloned_loop_| shares the same block as |loop_|. |
| 88 | // We mutate all branches from |cloned_loop_| block to |loop_|'s merge into a |
| 89 | // branch to |loop_|'s header (so header will also be the merge of |
| 90 | // |cloned_loop_|). |
| 91 | uint32_t cloned_loop_exit = 0; |
| 92 | for (uint32_t pred_id : cfg.preds(loop_->GetMergeBlock()->id())) { |
| 93 | if (loop_->IsInsideLoop(pred_id)) continue; |
| 94 | BasicBlock* bb = cfg.block(pred_id); |
| 95 | assert(cloned_loop_exit == 0 && "The loop has multiple exits."); |
| 96 | cloned_loop_exit = bb->id(); |
| 97 | bb->ForEachSuccessorLabel([this](uint32_t* succ) { |
| 98 | if (*succ == loop_->GetMergeBlock()->id()) |
| 99 | *succ = loop_->GetHeaderBlock()->id(); |
| 100 | }); |
| 101 | } |
| 102 | |
| 103 | // Update cfg. |
| 104 | cfg.RemoveNonExistingEdges(loop_->GetMergeBlock()->id()); |
| 105 | cfg.AddEdge(cloned_loop_exit, loop_->GetHeaderBlock()->id()); |
nothing calls this directly
no test coverage detected