| 190 | } |
| 191 | |
| 192 | BasicBlock* CFG::SplitLoopHeader(BasicBlock* bb) { |
| 193 | assert(bb->GetLoopMergeInst() && "Expecting bb to be the header of a loop."); |
| 194 | |
| 195 | Function* fn = bb->GetParent(); |
| 196 | IRContext* context = module_->context(); |
| 197 | |
| 198 | // Get the new header id up front. If we are out of ids, then we cannot split |
| 199 | // the loop. |
| 200 | uint32_t new_header_id = context->TakeNextId(); |
| 201 | if (new_header_id == 0) { |
| 202 | return nullptr; |
| 203 | } |
| 204 | |
| 205 | // Find the insertion point for the new bb. |
| 206 | Function::iterator header_it = std::find_if( |
| 207 | fn->begin(), fn->end(), |
| 208 | [bb](BasicBlock& block_in_func) { return &block_in_func == bb; }); |
| 209 | assert(header_it != fn->end()); |
| 210 | |
| 211 | const std::vector<uint32_t>& pred = preds(bb->id()); |
| 212 | // Find the back edge |
| 213 | BasicBlock* latch_block = nullptr; |
| 214 | Function::iterator latch_block_iter = header_it; |
| 215 | for (; latch_block_iter != fn->end(); ++latch_block_iter) { |
| 216 | // If blocks are in the proper order, then the only branch that appears |
| 217 | // after the header is the latch. |
| 218 | if (std::find(pred.begin(), pred.end(), latch_block_iter->id()) != |
| 219 | pred.end()) { |
| 220 | break; |
| 221 | } |
| 222 | } |
| 223 | assert(latch_block_iter != fn->end() && "Could not find the latch."); |
| 224 | latch_block = &*latch_block_iter; |
| 225 | |
| 226 | RemoveSuccessorEdges(bb); |
| 227 | |
| 228 | // Create the new header bb basic bb. |
| 229 | // Leave the phi instructions behind. |
| 230 | auto iter = bb->begin(); |
| 231 | while (iter->opcode() == spv::Op::OpPhi) { |
| 232 | ++iter; |
| 233 | } |
| 234 | |
| 235 | BasicBlock* new_header = bb->SplitBasicBlock(context, new_header_id, iter); |
| 236 | context->AnalyzeDefUse(new_header->GetLabelInst()); |
| 237 | |
| 238 | // Update cfg |
| 239 | RegisterBlock(new_header); |
| 240 | |
| 241 | // Update bb mappings. |
| 242 | context->set_instr_block(new_header->GetLabelInst(), new_header); |
| 243 | new_header->ForEachInst([new_header, context](Instruction* inst) { |
| 244 | context->set_instr_block(inst, new_header); |
| 245 | }); |
| 246 | |
| 247 | // If |bb| was the latch block, the branch back to the header is not in |
| 248 | // |new_header|. |
| 249 | if (latch_block == bb) { |