CACAO
ListSchedulingPass.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/ListSchedulingPass.cpp - ListSchedulingPass
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 
35 
36 #include "toolbox/logging.hpp"
37 
38 // define name for debugging (see logging.hpp)
39 #define DEBUG_NAME "compiler2/ListSchedulingPass"
40 
41 namespace cacao {
42 namespace jit {
43 namespace compiler2 {
44 
45 namespace {
46 
47 class MyComparator {
48 private:
49 
50  const GlobalSchedule* GS;
51 
52  unsigned users(Instruction *I) const {
53  unsigned users = 0;
54  for (Instruction::UserListTy::const_iterator i = I->user_begin(),
55  e = I->user_end(); i != e; ++i) {
56  Instruction *user = *i;
57  // only instructions in this basic block
58  if (GS->get(user) == GS->get(I)) {
59  users++;
60  }
61  }
62  return users;
63  }
64 
65 public:
66 
67  MyComparator(const GlobalSchedule* GS) : GS(GS) {}
68 
69  bool operator() (Instruction* lhs, Instruction* rhs) const {
70  if (lhs->get_opcode() != rhs->get_opcode()) {
71  // BeginInst always first!
72  if (lhs->to_BeginInst()) return false;
73  if (rhs->to_BeginInst()) return true;
74  // EndInst always last!
75  if (rhs->to_EndInst()) return false;
76  if (lhs->to_EndInst()) return true;
77  // PHIs right after BeginInst
78  if (lhs->to_PHIInst()) return false;
79  if (rhs->to_PHIInst()) return true;
80  // LOADInst first
81  if (lhs->to_LOADInst()) return false;
82  if (rhs->to_LOADInst()) return true;
83  }
84  // prioritize instruction with fewer users in the current bb
85  unsigned lhs_user = users(lhs);
86  unsigned rhs_user = users(rhs);
87  if (lhs_user == rhs_user) {
88  return InstPtrLess()(rhs,lhs);
89  }
90  return lhs_user > rhs_user;
91  }
92 };
93 
94 typedef alloc::priority_queue<Instruction*,alloc::deque<Instruction*>::type,MyComparator>::type PriorityQueueTy;
95 
96 struct FindLeader2 : public std::unary_function<Value*,void> {
98  GlobalSchedule *GS;
99  Instruction *I;
100  bool &leader;
101  /// constructor
102  FindLeader2(alloc::set<Instruction*>::type &scheduled, GlobalSchedule *GS, Instruction *I, bool &leader)
103  : scheduled(scheduled), GS(GS), I(I), leader(leader) {}
104  /// function call operator
105  void operator()(Value *value) {
106  Instruction *op = value->to_Instruction();
107  assert(op);
108  if (op != I && GS->get(I) == GS->get(op) && scheduled.find(op) == scheduled.end() ) {
109  leader = false;
110  }
111  }
112 };
113 
114 struct FindLeader : public std::unary_function<Instruction*,void> {
116  GlobalSchedule *GS;
117  PriorityQueueTy &ready;
118  BeginInst *BI;
119  /// constructor
120  FindLeader(alloc::set<Instruction*>::type &scheduled, GlobalSchedule *GS, PriorityQueueTy &ready, BeginInst *BI)
121  : scheduled(scheduled), GS(GS), ready(ready), BI(BI) {}
122 
123  /// function call operator
124  void operator()(Instruction* I) {
125  // only instructions in this basic block
126  if (GS->get(I) != GS->get(BI)) {
127  return;
128  }
129  bool leader = true;
130  // for each operand
131  std::for_each(I->op_begin(), I->op_end(), FindLeader2(scheduled, GS, I, leader));
132  // for each dependency
133  std::for_each(I->dep_begin(), I->dep_end(), FindLeader2(scheduled, GS, I, leader));
134  if (leader) {
135  LOG("leader: " << I << nl);
136  ready.push(I);
137  }
138  }
139 };
140 
141 } // end anonymous namespace
142 
144  // reference to the instruction list of the current basic block
145  InstructionListTy &inst_list = map[BI];
146  // set of already scheduled instructions
148  // queue of ready instructions
149  MyComparator comp = MyComparator(GS);
150  PriorityQueueTy ready(comp);
151  // Begin is always the first instruction
152  ready.push(BI);
153  LOG3(Cyan<<"BI: " << BI << reset_color << nl);
155  e = GS->inst_end(BI); i != e; ++i) {
156  Instruction *I = *i;
157  // BI is already in the queue
158  if (I->to_BeginInst() == BI)
159  continue;
160  LOG3("Instruction: " << I << nl);
161  //fill_ready(GS, ready, I);
162  bool leader = true;
163 
164  LOG3("schedule(initial leader): " << I << " #op " << I->op_size() << " #dep " << I->dep_size() << nl);
165  // for each operand
166  std::for_each(I->op_begin(), I->op_end(), FindLeader2(scheduled, GS, I, leader));
167  // for each dependency
168  std::for_each(I->dep_begin(), I->dep_end(), FindLeader2(scheduled, GS, I, leader));
169 
170  if (leader) {
171  LOG("initial leader: " << I << nl);
172  ready.push(I);
173  }
174  }
175 
176  while (!ready.empty()) {
177  Instruction *I = ready.top();
178  ready.pop();
179  if (scheduled.find(I) != scheduled.end()){
180  continue;
181  }
182  inst_list.push_back(I);
183  LOG("insert: " << I << nl);
184  scheduled.insert(I);
185  // for all users
186  std::for_each(I->user_begin(), I->user_end(), FindLeader(scheduled,GS,ready,BI));
187  // for all dependant instruction
188  std::for_each(I->rdep_begin(), I->rdep_end(), FindLeader(scheduled,GS,ready,BI));
189  }
190 #if defined(ENABLE_LOGGING)
191  for(const_inst_iterator i = inst_begin(BI), e = inst_end(BI); i != e ; ++i) {
192  Instruction *I = *i;
193  LOG(I<<nl);
194  }
195 #endif
196  assert( std::distance(inst_begin(BI),inst_end(BI)) == std::distance(GS->inst_begin(BI),GS->inst_end(BI)) );
197 }
198 
200  M = JD.get_Method();
201  GS = get_Pass<ScheduleClickPass>();
202 
203  for (Method::const_bb_iterator i = M->bb_begin(), e = M->bb_end() ; i != e ; ++i) {
204  BeginInst *BI = *i;
205  LOG("ListScheduling: " << BI << nl);
206  schedule(BI);
207  }
208 #if defined(ENABLE_LOGGING)
209  LOG("Schedule:" << nl);
210  for (Method::const_bb_iterator i = M->bb_begin(), e = M->bb_end() ; i != e ; ++i) {
211  BeginInst *BI = *i;
212  for(const_inst_iterator i = inst_begin(BI), e = inst_end(BI); i != e ; ++i) {
213  Instruction *I = *i;
214  LOG(I<<nl);
215  }
216  }
217 #endif
218  return true;
219 }
220 
222  for (Method::const_iterator i = M->begin(), e = M->end(); i!=e; ++i) {
223  Instruction *I = *i;
224  bool found = false;
225  for (Method::const_bb_iterator i = M->bb_begin(), e = M->bb_end(); i!=e; ++i) {
226  BeginInst *BI = *i;
227  if (std::find(inst_begin(BI),inst_end(BI),I) != inst_end(BI)) {
228  found = true;
229  }
230  }
231  if (!found) {
232  ERROR_MSG("Instruction not Scheduled!","Instruction: " << I);
233  return false;
234  }
235  }
236  return true;
237 }
238 
239 // pass usage
243  return PU;
244 }
245 
246 // register pass
247 static PassRegistry<ListSchedulingPass> X("ListSchedulingPass");
248 
249 } // end namespace compiler2
250 } // end namespace jit
251 } // end namespace cacao
252 
253 
254 /*
255  * These are local overrides for various environment variables in Emacs.
256  * Please do not remove this and leave it at the end of the file, where
257  * Emacs will automagically detect them.
258  * ---------------------------------------------------------------------
259  * Local variables:
260  * mode: c++
261  * indent-tabs-mode: t
262  * c-basic-offset: 4
263  * tab-width: 4
264  * End:
265  * vim:noexpandtab:sw=4:ts=4:
266  */
const_inst_iterator inst_end(const BeginInst *BI) const
std::set< Instruction *, std::less< Instruction * >, Allocator< Instruction * > > type
Definition: set.hpp:38
const_dep_iterator rdep_begin() const
virtual bool run(JITData &JD)
Run the Pass.
void schedule(BeginInst *begin)
Schedule the instructions within the block that starts at begin.
UserListTy::const_iterator user_begin() const
Definition: Value.hpp:72
BeginInst * BI
const_inst_iterator inst_begin(const BeginInst *BI) const
BBListTy::const_iterator const_bb_iterator
Definition: MethodC2.hpp:71
const_bb_iterator bb_end() const
Definition: MethodC2.hpp:159
This Instruction marks the start of a basic block.
u2 op
Definition: disass.cpp:129
const_dep_iterator dep_begin() const
#define ERROR_MSG(EXPR_SHORT, EXPR_LONG)
Definition: logging.hpp:124
UserListTy::const_iterator user_end() const
Definition: Value.hpp:73
GlobalSchedule * GS
The current GlobalSchedule of the processed Method.
const_inst_iterator inst_begin(const BeginInst *BI) const
alloc::set< Instruction * >::type & scheduled
Stores the interdependencies of a pass.
Definition: PassUsage.hpp:55
Instruction super class.
Definition: Instruction.hpp:75
virtual bool verify() const
Verify the Result.
const_dep_iterator rdep_end() const
MIIterator i
ResetColor reset_color
Definition: OStream.cpp:61
InstructionListTy::const_iterator const_iterator
Definition: MethodC2.hpp:69
const_iterator end() const
Definition: MethodC2.hpp:147
const_op_iterator op_begin() const
#define LOG3(STMT)
Definition: logging.hpp:94
MIIterator e
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
#define I(value)
Definition: codegen.c:279
alloc::unordered_set< Instruction * >::type::const_iterator const_inst_iterator
Represents the result of the addition of a certain IR-variable with a certain constant.
Definition: Value.hpp:36
jmethodID jint const void jint const jvmtiAddrLocationMap * map
Definition: jvmti.h:338
const GlobalSchedule * GS
const_iterator begin() const
Definition: MethodC2.hpp:143
const_dep_iterator dep_end() const
virtual BeginInst * to_BeginInst()
Definition: Instruction.hpp:81
virtual PassUsage & get_PassUsage(PassUsage &PU) const
Set the requirements for the pass.
PriorityQueueTy & ready
const_inst_iterator inst_end(const BeginInst *BI) const
static PassRegistry< BasicBlockSchedulingPass > X("BasicBlockSchedulingPass")
Nl nl
Definition: OStream.cpp:56
const_op_iterator op_end() const
void add_requires()
PassName is required.
Definition: PassUsage.hpp:78
bool & leader
const_bb_iterator bb_begin() const
Definition: MethodC2.hpp:155