CACAO
BasicBlockSchedulingPass.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/BasicBlockSchedulingPass.cpp - BasicBlockSchedulingPass
2 
3  Copyright (C) 2013
4  CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 
6  This file is part of CACAO.
7 
8  This program is free software; you can redistribute it and/or
9  modify it under the terms of the GNU General Public License as
10  published by the Free Software Foundation; either version 2, or (at
11  your option) any later version.
12 
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21  02110-1301, USA.
22 
23 */
24 
30 #include "toolbox/logging.hpp"
31 
36 
37 #define DEBUG_NAME "compiler2/BasicBlockSchedulingPass"
38 
39 #define VERIFY_LOOP_PROPERTY 1
40 #define VERIFY_PRED_PROPERTY 1
41 
42 namespace cacao {
43 namespace jit {
44 namespace compiler2 {
45 
46 
48 private:
49  // XXX use unordered map and hash
56 
60 
61  bool is_scheduled(BeginInst* BI) const {
62  return std::find(bb_sched.begin(),bb_sched.end(), BI) != bb_sched.end();
63  }
64 
65  bool is_ready(BeginInst* BI) const {
67  i != e; ++i) {
68  BeginInst *pred = *i;
69  if (!is_scheduled(pred) && !LT->is_backedge(pred,BI)) {
70  return false;
71  }
72  }
73  return true;
74  }
75 
77  LOG3(Magenta << "schedule_loop: " << loop << reset_color << nl);
78  BeginSetTy unsched(loopmap[loop]);
79  LoopSetTy subloops;
80  if (loop) {
81  subloops.insert(loop->loop_begin(),loop->loop_end());
82  }
83  else {
84  subloops.insert(LT->loop_begin(),LT->loop_end());
85  }
86  while ( !unsched.empty() || !subloops.empty()) {
87  // try schedule loop bbs
88  bool changed = true;
89  while (changed) {
90  changed = false;
91  for(BeginSetTy::iterator i = unsched.begin(), e = unsched.end() ; i != e; ++i) {
92  BeginInst *BI = *i;
93  if ( is_ready(BI) ) {
94  // idom scheduled
95  bb_sched.push_back(BI);
96  unsched.erase(i);
97  LOG3(Green <<" scheduled: " << BI << reset_color<<nl);
98  changed=true;
99  break;
100  } else {
101  LOG3(Red <<" not scheduled: " << BI << reset_color <<nl);
102  }
103  }
104  }
105  assert(unsched.empty() || !subloops.empty());
106  for(LoopSetTy::iterator i = subloops.begin() , e = subloops.end(); i != e; ++i) {
107  Loop *subloop = *i;
108  if (is_ready(subloop->get_header()) ) {
109  LOG3("schedule subloop of " << loop << nl);
110  schedule_loop(*i);
111  subloops.erase(i);
112  break;
113  }
114  }
115  }
116  LOG3("finished: " << loop << nl);
117  }
118 public:
119  /// constructor
121  // fill maps
122  for(Method::const_bb_iterator i = M->bb_begin(), e = M->bb_end() ; i != e; ++i) {
123  BeginInst *BI = *i;
124  loopmap[LT->get_Loop(BI)].insert(BI);
125  }
126  // start scheduling
127  schedule_loop(NULL);
128  }
129  BeginListTy::const_iterator begin() const { return bb_sched.begin(); }
130  BeginListTy::const_iterator end() const { return bb_sched.end(); }
131 };
132 
134  M = JD.get_Method();
135  LoopTree *LT = get_Pass<LoopPass>();
136 
137  // schedule loops
138  LoopScheduler loop_scheduler(M,LT);
139 
140  insert(begin(),loop_scheduler.begin(),loop_scheduler.end());
141 
142  #if 0
143  // random order
145  std::remove(bbs.begin(),bbs.end(),M->get_init_bb());
146  std::random_shuffle(bbs.begin(),bbs.end());
147  bbs.push_front(M->get_init_bb());
148  insert(begin(),bbs.begin(),bbs.end());
149  #endif
150 
151  if (DEBUG_COND) {
152  LOG("BasicBlockSchedule:" << nl);
153  for (const_bb_iterator i = bb_begin(), e = bb_end(); i != e; ++i) {
154  LOG(*i << nl);
155  }
156  }
157  return true;
158 }
159 
160 namespace {
161 #if VERIFY_LOOP_PROPERTY
162 // push loops recursively in reverse order
163 void push_loops_inbetween(alloc::list<Loop*>::type &active, Loop* inner, Loop* outer) {
164  if (inner == outer) return;
165  push_loops_inbetween(active,inner->get_parent(),outer);
166  active.push_back(inner);
167 }
168 #endif
169 } // anonymous namespace
170 
171 
172 namespace tree {
173 
174 template <>
175 inline Loop* get_parent(Loop* a) {
176  return a->get_parent();
177 }
178 
179 template <>
180 inline Loop* get_root() {
181  return NULL;
182 }
183 
184 } // end namespace tree
185 
187  // check init basic block
188  if (*bb_begin() != M->get_init_bb()) {
189  ERROR_MSG("Schedule does not start with init basic block!",
190  "Init basic block is " << M->get_init_bb()
191  << " but schedule starts with " << *bb_begin());
192  return false;
193  }
194  // check if ordering (obsolete)
195  #if 0
196  for (unsigned i = 0, e = bb_list.size() ; i < e ; ++i) {
197  BeginInst *BI = bb_list[i];
198  assert(BI);
199  EndInst *EI = BI->get_EndInst();
200  if (EI->to_IFInst()) {
201  EndInst::SuccessorListTy::const_iterator it = EI->succ_begin();
202  ++it;
203  assert(it != EI->succ_end());
204  assert(i+1 < e);
205  if (it->get() != bb_list[i+1]) {
206  return false;
207  }
208  }
209  }
210  #endif
211  #if VERIFY_PRED_PROPERTY || VERIFY_LOOP_PROPERTY
212  LoopTree *LT = get_Pass<LoopPass>();
213  #endif
214  #if VERIFY_PRED_PROPERTY
215  // check predecessor property
218  i !=e ; ++i) {
219  BeginInst *BI = *i;
220  for (BeginInst::const_pred_iterator i = BI->pred_begin(), e = BI->pred_end();
221  i != e; ++i) {
222  BeginInst *pred = *i;
223  if (handled.find(pred) == handled.end() && !LT->is_backedge(pred,BI)) {
224  ERROR_MSG("Predecessor property violated!","predecessor (" << *pred
225  << ") of " << *BI << "not already scheduled" );
226  return false;
227  }
228  }
229  handled.insert(BI);
230  }
231  #endif
232  // check contiguous loop property
233  #if VERIFY_LOOP_PROPERTY
234  alloc::set<Loop*>::type finished;
236  // sentinel
237  active.push_back(NULL);
239  i !=e ; ++i) {
240  BeginInst *BI = *i;
241  Loop *loop = LT->get_Loop(BI);
242  Loop *top = active.back();
243 
244  if ( loop && finished.find(loop) != finished.end()) {
245  ERROR_MSG("Loop property violated!","Loop " << *loop
246  << " already finished but " << *BI << " occurred" );
247  return false;
248  }
249 
250  if (loop == top) {
251  // same loop
252  continue;
253  }
254  // new loop(s)
255  // find least common ancestor
256  Loop *lca = tree::find_least_common_ancestor(loop, top);
257  while (top != lca) {
258  assert(!active.empty());
259  finished.insert(top);
260  active.pop_back();
261  top = active.back();
262  }
263  push_loops_inbetween(active,loop,lca);
264  }
265  #endif
266  return true;
267 }
268 
269 // pass usage
271  PU.add_requires<LoopPass>();
272  return PU;
273 }
274 
275 // the address of this variable is used to identify the pass
277 
278 // register pass
279 static PassRegistry<BasicBlockSchedulingPass> X("BasicBlockSchedulingPass");
280 
281 } // end namespace compiler2
282 } // end namespace jit
283 } // end namespace cacao
284 
285 
286 /*
287  * These are local overrides for various environment variables in Emacs.
288  * Please do not remove this and leave it at the end of the file, where
289  * Emacs will automagically detect them.
290  * ---------------------------------------------------------------------
291  * Local variables:
292  * mode: c++
293  * indent-tabs-mode: t
294  * c-basic-offset: 4
295  * tab-width: 4
296  * End:
297  * vim:noexpandtab:sw=4:ts=4:
298  */
std::set< Key, Compare, Allocator< Key > > type
Definition: set.hpp:38
alloc::list< BeginInst * >::type BeginListTy
virtual bool verify() const
Verify the Result.
#define DEBUG_COND
Definition: Debug.hpp:113
BBListTy::const_iterator const_bb_iterator
Definition: MethodC2.hpp:69
PredecessorListTy::const_iterator const_pred_iterator
T find_least_common_ancestor(T a, T b)
const_bb_iterator bb_end() const
Definition: MethodC2.hpp:153
This Instruction mark the start of a basic block.
MachineLoop * loop
This Instruction mark the end of a basic block.
std::deque< T, Allocator< T > > type
Definition: deque.hpp:38
alloc::unordered_set< BeginInst * >::type BeginSetTy
#define ERROR_MSG(EXPR_SHORT, EXPR_LONG)
Definition: logging.hpp:124
const_pred_iterator pred_begin() const
LoopScheduler(Method *M, LoopTree *LT)
constructor
std::list< T, Allocator< T > > type
Definition: list.hpp:38
alloc::unordered_set< Loop * >::type LoopSetTy
alloc::map< BeginInst *, BeginSetTy >::type DomSuccMapTy
BeginListTy::const_iterator end() const
SuccessorListTy::const_iterator succ_end() const
LoopBase * get_parent() const
Definition: LoopBase.hpp:62
Stores the interdependencies of a pass.
Definition: PassUsage.hpp:55
bool is_backedge(NodeType *src, NodeType *header) const
Definition: LoopBase.hpp:171
void insert(bb_iterator pos, InputIterator first, InputIterator last)
MIIterator i
alloc::set< BeginInst * >::type BeginSchedMapTy
SuccessorListTy::const_iterator succ_begin() const
ResetColor reset_color
Definition: OStream.cpp:61
#define LOG3(STMT)
Definition: logging.hpp:94
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
_Base::iterator iterator
Calculate the Loop Tree.
const_pred_iterator pred_end() const
const Method & M
BasicBlockListTy::const_iterator const_bb_iterator
NodeType * get_header() const
Definition: LoopBase.hpp:56
LoopType * get_Loop(NodeType *BI) const
Get the inner most loop which contains BI or NULL if not contained in any loop.
Definition: LoopBase.hpp:148
static PassRegistry< BasicBlockSchedulingPass > X("BasicBlockSchedulingPass")
Nl nl
Definition: OStream.cpp:56
alloc::map< Loop *, BeginSetTy >::type LoopMapTy
virtual PassUsage & get_PassUsage(PassUsage &PA) const
Set the requirements for the pass.
BeginInst * get_init_bb() const
Definition: MethodC2.hpp:133
void add_requires()
PassName is required.
Definition: PassUsage.hpp:78
BeginListTy::const_iterator begin() const
const_bb_iterator bb_begin() const
Definition: MethodC2.hpp:149