11#include " blocks/loops.h"
22#include < algorithm>
33
4+ std::shared_ptr<loop> loop_info::allocate_loop (std::shared_ptr<basic_block> header) {
5+ if (!header)
6+ return nullptr ;
7+
8+ loops.push_back (std::make_shared<loop>(header));
9+ bb_loop_map[header->id ] = loops.back ();
10+ return loops.back ();
11+ }
12+
413void loop_info::analyze () {
514 std::vector<int > idom = dta.get_idom ();
6- for (unsigned int i = 0 ; i < idom.size (); i++) {
7- std::cout << i << " : " << idom[i] << " \n " ;
15+
16+ for (int idom_id: dta.get_postorder_idom_map ()) {
17+ std::vector<int > backedges;
18+ int header = idom_id;
19+
20+ for (auto backedge: dta.cfg_ [header]->predecessor ) {
21+ if (dta.dominates (header, backedge->id ) && dta.is_reachable_from_entry (backedge->id )) {
22+ backedges.push_back (backedge->id );
23+ }
24+ }
25+
26+ if (!backedges.empty ()) {
27+ std::shared_ptr<loop> new_loop = allocate_loop (dta.cfg_ [header]);
28+ if (!new_loop)
29+ continue ;
30+
31+ int num_blocks = 0 ;
32+ int num_subloops = 0 ;
33+
34+ auto backedge_iter = backedges.begin ();
35+ // do a reverse CFG traversal to map basic blocks in this loop.
36+ basic_block::cfg_block worklist (backedges.size ());
37+ std::generate (worklist.begin (), worklist.end (), [&backedge_iter, this ](){
38+ return dta.cfg_ [*(backedge_iter++)];
39+ });
40+
41+ while (!worklist.empty ()) {
42+ unsigned int predecessor_bb_id = worklist.back ()->id ;
43+ worklist.pop_back ();
44+
45+ auto subloop_iter = bb_loop_map.find (predecessor_bb_id);
46+ if (subloop_iter == bb_loop_map.end ()) {
47+ if (!dta.is_reachable_from_entry (predecessor_bb_id))
48+ continue ;
49+
50+ bb_loop_map[predecessor_bb_id] = new_loop;
51+ ++num_blocks;
52+ // loop has no blocks between header and backedge
53+ if (predecessor_bb_id == new_loop->header_block ->id )
54+ continue ;
55+
56+ worklist.insert (worklist.end (), dta.cfg_ [predecessor_bb_id]->predecessor .begin (), dta.cfg_ [predecessor_bb_id]->predecessor .end ());
57+ }
58+ else {
59+ // this block has already been discovered, mapped to some other loop
60+ // find the outermost loop
61+ std::shared_ptr<loop> subloop = subloop_iter->second ;
62+ while (subloop->parent_loop ) {
63+ subloop = subloop->parent_loop ;
64+ }
65+
66+ if (subloop == new_loop)
67+ continue ;
68+
69+ // discovered a subloop of this loop
70+ subloop->parent_loop = new_loop;
71+ ++num_subloops;
72+ num_blocks = num_blocks + subloop->blocks .size ();
73+ predecessor_bb_id = subloop->header_block ->id ;
74+
75+ for (auto pred: dta.cfg_ [predecessor_bb_id]->predecessor ) {
76+ auto loop_iter = bb_loop_map.find (pred->id );
77+ // do not check if loop_iter != bb_loop_map.end(), as a results
78+ // basic blocks that are not directly part of the natural loops
79+ // are skipped, like loop latches.
80+ if (loop_iter->second != subloop)
81+ worklist.push_back (pred);
82+ }
83+ }
84+ }
85+ new_loop->subloops .reserve (num_subloops);
86+ new_loop->blocks .reserve (num_blocks);
87+ }
888 }
9- }
89+
90+ // populate all subloops and loops with blocks
91+ for (auto bb_id: dta.get_postorder ()) {
92+ auto subloop_iter = bb_loop_map.find (bb_id);
93+ std::shared_ptr<loop> subloop = nullptr ;
94+ if (subloop_iter != bb_loop_map.end () && (subloop = subloop_iter->second ) && dta.cfg_ [bb_id] == subloop_iter->second ->header_block ) {
95+ // check if it is the outermost loop
96+ if (subloop->parent_loop != nullptr ) {
97+ subloop->parent_loop ->subloops .push_back (subloop);
98+ }
99+ else {
100+ top_level_loops.push_back (subloop);
101+ }
102+
103+ std::reverse (subloop->blocks .begin (), subloop->blocks .end ());
104+ std::reverse (subloop->subloops .begin (), subloop->subloops .end ());
105+
106+ subloop = subloop->parent_loop ;
107+ }
108+
109+ while (subloop) {
110+ subloop->blocks .push_back (dta.cfg_ [bb_id]);
111+ subloop = subloop->parent_loop ;
112+ }
113+ }
114+ }
0 commit comments