1 /** 2 * Copyright 2023 Huawei Technologies Co., Ltd 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 #include "pipeline/jit/pi/graph_capture/loop.h" 17 #include <fstream> 18 #include <string> 19 #include "pipeline/jit/pi/graph_capture/cfg.h" 20 #include "pipeline/jit/pi/graph_capture/graph.h" 21 22 namespace mindspore { 23 namespace pijit { Dump() const24std::string LoopInfo::Dump() const { 25 std::stringstream os; 26 os << "header: " << header_->id(); 27 os << " backedge: "; 28 for (auto *bb : backedges_) { 29 os << bb->id() << " "; 30 } 31 os << "\n members: "; 32 for (auto *bb : loop_members_) { 33 os << bb->id() << " "; 34 } 35 os << "\n exits: "; 36 for (auto *bb : exits_) { 37 os << bb->id() << " "; 38 } 39 os << "\n"; 40 return os.str(); 41 } 42 LoopFinder(Graph * graph)43LoopFinder::LoopFinder(Graph *graph) : graph_(*graph), alloc_(graph->allocator()) {} 44 UpdateLoop2Graph()45void LoopFinder::UpdateLoop2Graph() { 46 for (LoopInfo *loop = loops_; loop != nullptr; loop = loop->next()) { 47 graph_.AddLoop(loop); 48 } 49 } 50 FormSimpleLoopInfo()51void LoopFinder::FormSimpleLoopInfo() { 52 const std::unique_ptr<CFG> &cfg = graph_.GetCFG(); 53 if (cfg == nullptr) { 54 return; 55 } 56 LoopInfo *tail_loop = nullptr; 57 for (Block *bb : *cfg) { 58 if (!bb->is_loop_head() || bb->GetJumpBB() == nullptr || bb->GetJumpBB()->id() == bb->id()) { 59 continue; 60 } 61 LoopInfo *loop = alloc_.NewLoopInfo<LoopInfo>(); 62 loop->set_header(bb); 63 for (Block *pred : bb->pred_bbs()) { 64 if (pred->instrs().front().bci() > bb->instrs().front().bci()) { 65 loop->InsertBackedge(pred); 66 } 67 } 68 Block *exitBB = bb->GetJumpBB(); 69 // find head's jump BB or find the BB after the max backend edge 70 for (Block *pred : loop->backedges()) { 71 if (pred->id() + 1 < cfg->bb_pool().size()) { 72 if (cfg->bb_pool()[pred->id() + 1].get()->instrs().front().bci() > exitBB->instrs().front().bci()) { 73 exitBB = cfg->bb_pool()[pred->id() + 1].get(); 74 } 75 } 76 } 77 loop->InsertExit(exitBB); 78 if (loops_ == nullptr) { 79 loops_ = loop; 80 } else { 81 tail_loop->set_next(loop); 82 loop->set_prev(tail_loop); 83 } 84 for (uint32_t i = bb->id(); i < exitBB->id(); ++i) { 85 loop->InsertLoopMembers(cfg->bb_pool()[i].get()); 86 } 87 tail_loop = loop; 88 } 89 UpdateLoop2Graph(); 90 } 91 } // namespace pijit 92 } // namespace mindspore 93