| 453 | } |
| 454 | |
| 455 | Pass::Status LoopFissionPass::Process() { |
| 456 | bool changed = false; |
| 457 | |
| 458 | for (Function& f : *context()->module()) { |
| 459 | // We collect all the inner most loops in the function and run the loop |
| 460 | // splitting util on each. The reason we do this is to allow us to iterate |
| 461 | // over each, as creating new loops will invalidate the loop iterator. |
| 462 | std::vector<Loop*> inner_most_loops{}; |
| 463 | LoopDescriptor& loop_descriptor = *context()->GetLoopDescriptor(&f); |
| 464 | for (Loop& loop : loop_descriptor) { |
| 465 | if (!loop.HasChildren() && ShouldSplitLoop(loop, context())) { |
| 466 | inner_most_loops.push_back(&loop); |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | // List of new loops which meet the criteria to be split again. |
| 471 | std::vector<Loop*> new_loops_to_split{}; |
| 472 | |
| 473 | while (!inner_most_loops.empty()) { |
| 474 | for (Loop* loop : inner_most_loops) { |
| 475 | LoopFissionImpl impl{context(), loop}; |
| 476 | |
| 477 | // Group the instructions in the loop into two different sets of related |
| 478 | // instructions. If we can't group the instructions into the two sets |
| 479 | // then we can't split the loop any further. |
| 480 | if (!impl.GroupInstructionsByUseDef()) { |
| 481 | continue; |
| 482 | } |
| 483 | |
| 484 | if (impl.CanPerformSplit()) { |
| 485 | Loop* second_loop = impl.SplitLoop(); |
| 486 | if (!second_loop) { |
| 487 | return Status::Failure; |
| 488 | } |
| 489 | changed = true; |
| 490 | context()->InvalidateAnalysesExceptFor( |
| 491 | IRContext::kAnalysisLoopAnalysis); |
| 492 | |
| 493 | // If the newly created loop meets the criteria to be split, split it |
| 494 | // again. |
| 495 | if (ShouldSplitLoop(*second_loop, context())) |
| 496 | new_loops_to_split.push_back(second_loop); |
| 497 | |
| 498 | // If the original loop (now split) still meets the criteria to be |
| 499 | // split, split it again. |
| 500 | if (ShouldSplitLoop(*loop, context())) |
| 501 | new_loops_to_split.push_back(loop); |
| 502 | } |
| 503 | } |
| 504 | |
| 505 | // If the split multiple times flag has been set add the new loops which |
| 506 | // meet the splitting criteria into the list of loops to be split on the |
| 507 | // next iteration. |
| 508 | if (split_multiple_times_) { |
| 509 | inner_most_loops = std::move(new_loops_to_split); |
| 510 | new_loops_to_split = {}; |
| 511 | } else { |
| 512 | break; |
nothing calls this directly
no test coverage detected