CACAO
LivetimeInterval.cpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/LivetimeInterval.cpp - LivetimeInterval
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 
27 
28 #include "toolbox/logging.hpp"
29 
30 #define DEBUG_NAME "compiler2/LivetimeInterval"
31 
32 namespace cacao {
33 namespace jit {
34 namespace compiler2 {
35 
37  //LOG("first " << **first.get_iterator() << " last " << **last.get_iterator() << nl);
38  assert(!(last < first));
39 
40  insert_usedef(first);
41  insert_usedef(last);
42 
43  LivetimeRange range(first,last);
44  for (IntervalListTy::iterator i = intervals.begin(), e = intervals.end();
45  i != e; ) {
47  if (range.end < current.start) {
48  break;
49  }
50  if (current.end < range.start) {
51  ++i;
52  continue;
53  }
54  if (current.start <= range.start) {
55  range.start = current.start;
56  }
57  if (range.end < current.end) {
58  range.end = current.end;
59  }
60  i = intervals.erase(i);
61  }
62  // new interval
63  intervals.push_front(range);
64 }
65 
67  if(intervals.empty()) {
68  add_range(from, to);
69  } else {
70  insert_usedef(from);
71  intervals.front().start = from;
72  }
73 }
74 
77 
78  if (!empty() && back().end < pos) {
80  }
81  for (const_iterator i = begin(), e = end(); i != e; ++i) {
82  if (pos < i->start)
83  break;
84  if (pos <= i->end) {
86  }
88  }
89  return state;
90 }
91 
94 
95  if (!empty() && back().end.get_iterator() < pos) {
97  }
98  for (const_iterator i = begin(), e = end(); i != e; ++i) {
99  if (pos < i->start.get_iterator())
100  break;
101  if (pos <= i->end.get_iterator()) {
103  }
105  }
106  return state;
107 }
108 
110  return uses.find(UseDef(UseDef::PseudoUse,pos)) != uses.end();
111 }
112 
114  return defs.find(UseDef(UseDef::PseudoDef,pos)) != defs.end();
115 }
116 
117 
119  const LivetimeInterval &b, UseDef pos, UseDef end) {
120  for(LivetimeInterval::const_iterator a_i = a.begin(), b_i = b.begin(),
121  a_e = a.end(), b_e = b.end() ; a_i != a_e && b_i != b_e ; ) {
122 
123  if (a_i->end < b_i->start) {
124  ++a_i;
125  continue;
126  }
127  if (b_i->end < a_i->start) {
128  ++b_i;
129  continue;
130  }
131  return std::max(a_i->start,b_i->start);
132  }
133  return end;
134 }
135 
137  return OS << "LivetimeIntervalImpl (" << lti.front().start << ") in " << *lti.get_operand();
138 }
139 
141  //LOG2("get_operand(this:" << *this << " pos:" << pos << ")" <<nl);
142  if (back().end.get_iterator() < pos) {
143  if (!has_next()) {
144  MIIterator pre = pos;
145  --pre;
146  LOG("pre " << *pre << nl);
147  ++pre;
148  ++pre;
149  LOG("post " << *pre << nl);
150  // XXX
151  return get_operand();
152  }
153  assert_msg(has_next(),"end: " << back().end.get_iterator() << " pos " << pos);
154  LivetimeInterval lti_next = get_next();
155  assert(lti_next.pimpl);
156  return lti_next.get_operand(pos);
157  }
158  assert(!(pos < front().start.get_iterator()));
159  return get_operand();
160 }
161 
163  // search use
164  for (const_use_iterator i = use_begin(), e = use_end(); i != e; ++i) {
165  if (pos < *i) {
166  UseDef use = *i;
167  // search def
168  for (const_def_iterator i = def_begin(), e = def_end(); i != e; ++i) {
169  if (pos < *i) {
170  if (*i < use)
171  return *i;
172  break;
173  }
174  }
175  return use;
176  }
177  }
178  // possible because phi functions do not have use sites
179  return end;
180 }
181 
183  // copy uses
184  LOG2("copy uses" << nl);
185  {
186  const_use_iterator i = from->use_begin(), e = from->use_end();
187  for (; i!= e && *i < pos; ++i) {
188  LOG2(" keep " << *i << nl);
189  }
190  while(i != e) {
191  const_use_iterator tmp = i++;
192  LOG2(" move " << *tmp << nl);
193  to->uses.insert(*tmp);
194  from->uses.erase(tmp);
195  }
196  }
197  LOG2("copy defs" << nl);
198  // copy defs
199  {
200  const_def_iterator i = from->def_begin(), e = from->def_end();
201  for (; i!= e && *i < pos; ++i) {
202  LOG2(" keep " << *i << nl);
203  }
204  while(i != e) {
205  const_def_iterator tmp = i++;
206  LOG2(" move " << *tmp << nl);
207  to->defs.insert(*tmp);
208  from->defs.erase(tmp);
209  }
210  }
211 }
212 
214  LOG2("split_active " << *this << " at " << pos << nl);
215  #if defined(ENABLE_LOGGING)
216  if (DEBUG_COND_N(3)) {
217  MIIterator tmp = pos;
218  LOG3("pre " << --tmp << nl);
219  LOG3(">> " << ++tmp << nl);
220  LOG3("post " << ++tmp << nl);
221  }
222  #endif
223  MachineInstruction *MI = *pos;
224  assert(!has_next());
225  assert(get_State(pos) == LivetimeInterval::Active);
226  assert(MI->op_size() == 1);
227  assert(MI->is_move());
228 
229  UseDef use(UseDef::Use, pos, &MI->get(0));
230  UseDef def(UseDef::Def, pos, &MI->get_result());
231 
232  LOG2("new use: " << use << nl);
233  LOG2("new def: " << def << nl);
234 
235  // new iterval
237  LivetimeInterval &lti = *next;
238  lti.set_operand(def.get_operand()->op);
239 
240  // copy uses defs
241  move_use_def(this, lti.pimpl.get(), (current == NULL) ? def : *current);
242 
243  LOG2("copy ranges" << nl);
244  // copy ranges
245  iterator i = intervals.begin(), e = intervals.end();
246  for (; i != e && i->end < ((current == NULL) ? def : *current); ++i) {
247  LOG2(" keep " << *i << nl);
248  }
249  assert(i != e);
250  assert(i->start < def);
251 
252  // split range
253  iterator tmp = i++;
254  intervals.insert(tmp,LivetimeRange(tmp->start,use));
255  insert_usedef(use);
256  lti.pimpl->intervals.push_front(LivetimeRange(def,tmp->end));
257  lti.pimpl->insert_usedef(def);
258  intervals.erase(tmp);
259 
260  while(i != e) {
261  iterator tmp = i++;
262  LOG2(" move " << *tmp << nl);
263  lti.pimpl->intervals.push_back(*tmp);
264  intervals.erase(tmp);
265  }
266 
267  return lti;
268 }
269 
271  assert(!has_next());
272  assert(get_State(pos) == LivetimeInterval::Inactive);
273 
274  LOG2("Split " << *this << " at " << pos << nl);
275 
277  LivetimeInterval &lti = *next;
278  lti.set_operand(MO);
279 
280  // copy uses defs
281  move_use_def(this, lti.pimpl.get(), pos);
282 
283  LOG2("copy ranges" << nl);
284  // copy ranges
285  iterator i = intervals.begin(), e = intervals.end();
286  for (; i != e && i->start < pos; ++i) {
287  LOG2(" keep " << *i << nl);
288  }
289  assert(i != e);
290 
291  while(i != e) {
292  iterator tmp = i++;
293  LOG2(" move " << *tmp << nl);
294  lti.pimpl->intervals.push_back(*tmp);
295  intervals.erase(tmp);
296  }
297  assert(lti.front().start.is_pseudo());
298  assert((*lti.front().start.get_iterator())->is_label());
299  // set the start of the livetime interval to the end of the livetime hole
301  assert((*lti.front().start.get_iterator())->is_end());
302 
303  return lti;
304 }
305 
307  LOG2("split_phi_active " << *this << " at " << pos << nl);
308  #if !defined(NDEBUG)
309  MachineInstruction *MI = *pos;
310  assert(!has_next());
311  assert(get_State(pos) == LivetimeInterval::Active);
312  assert(MI->is_label());
313  #endif
314 
315  MIIterator pos_end = pos;
316  UseDef use(UseDef::PseudoUse, pos);
317  UseDef def(UseDef::PseudoDef, --pos_end);
318 
319  LOG2("new def: " << def << nl);
320  LOG2("new use: " << use << nl);
321 
322  // new iterval
324  LivetimeInterval &lti = *next;
325  lti.set_operand(MO);
326 
327  // copy uses defs
328  move_use_def(this, lti.pimpl.get(), def);
329 
330  LOG2("copy ranges" << nl);
331  // copy ranges
332  iterator i = intervals.begin(), e = intervals.end();
333  for (; i != e && i->end < use; ++i) {
334  LOG2(" keep " << *i << nl);
335  }
336  assert(i != e);
337 
338  // split range
339  iterator tmp = i++;
340  intervals.insert(tmp,LivetimeRange(tmp->start,def));
341  insert_usedef(use);
342  lti.pimpl->intervals.push_front(LivetimeRange(use,tmp->end));
343  lti.pimpl->insert_usedef(def);
344  intervals.erase(tmp);
345 
346  while(i != e) {
347  iterator tmp = i++;
348  LOG2(" move " << *tmp << nl);
349  lti.pimpl->intervals.push_back(*tmp);
350  intervals.erase(tmp);
351  }
352 
353  return lti;
354 }
355 
357  OS << "LivetimeInterval (" << lti.front().start << ") in "
358  << *lti.get_operand() << " (init:" << *lti.get_init_operand() << ")";
359  if (lti.get_hint()) {
360  OS << " (hint:" << lti.get_hint() << ")";
361  }
362  return OS;
363 }
365  if (!lti) {
366  return OS << "(LivetimeInterval) NULL";
367  }
368  return OS << *lti;
369 }
370 
371 OStream& operator<<(OStream &OS, const UseDef &usedef) {
372  if (usedef.is_use()) OS << "Use";
373  if (usedef.is_def()) OS << "Def";
374  if (usedef.is_pseudo()) OS << "Pseudo";
375  return OS << " " << usedef.get_iterator();
376 }
378  return OS << "LivetimeRange " << range.start << " - " << range.end;
379 }
380 
381 } // end namespace compiler2
382 } // end namespace jit
383 } // end namespace cacao
384 
385 
386 /*
387  * These are local overrides for various environment variables in Emacs.
388  * Please do not remove this and leave it at the end of the file, where
389  * Emacs will automagically detect them.
390  * ---------------------------------------------------------------------
391  * Local variables:
392  * mode: c++
393  * indent-tabs-mode: t
394  * c-basic-offset: 4
395  * tab-width: 4
396  * End:
397  * vim:noexpandtab:sw=4:ts=4:
398  */
LivetimeInterval split_active(MIIterator pos, UseDef *current=NULL)
const MachineOperandDesc & get(std::size_t i) const
MIIterator get_iterator() const
Get instruction iterator.
#define max(a, b)
Definition: lsra.hpp:80
LivetimeInterval::const_iterator const_iterator
argument_type from
static void move_use_def(LivetimeIntervalImpl *from, LivetimeIntervalImpl *to, UseDef pos)
void set_from(UseDef from, UseDef to)
Set from. If no interval available add range from to.
#define DEBUG_COND_N(VERBOSE)
Definition: Debug.hpp:112
MachineBasicBlock * current
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
void set_operand(MachineOperand *op)
Set the current store of the interval.
Simple stream class for formatted output.
Definition: OStream.hpp:141
OStream & operator<<(OStream &OS, const Conditional::CondID &cond)
Definition: Conditional.cpp:34
MIIterator i
#define LOG2(STMT)
Definition: logging.hpp:93
MIIterator pos
OStream & OS
bool is_use() const
Is a use position.
#define LOG3(STMT)
Definition: logging.hpp:94
MIIterator e
MachineOperand * get_init_operand() const
Get the initial operand.
#define LOG(STMT)
Analogous to DEBUG.
Definition: logging.hpp:91
LivetimeInterval split_phi_active(MIIterator pos, MachineOperand *MO)
Proxy to encode explicit and implicit successors.
UseDef next_intersection(const LivetimeInterval &a, const LivetimeInterval &b, UseDef pos, UseDef end)
IntervalListTy::const_iterator const_iterator
LivetimeInterval split_inactive(UseDef pos, MachineOperand *MO)
Operands that can be directly used by the machine (register, memory, stackslot)
const MachineOperandDesc & get_result() const
MachineOperand * get_operand() const
Get the current store of the interval.
#define assert_msg(COND, EXPR)
Definition: logging.hpp:107
MachineOperand * get_hint() const
Get the hint for the interval.
shared_ptr< LivetimeIntervalImpl > pimpl
bool is_def() const
Is a def position.
Nl nl
Definition: OStream.cpp:56
void add_range(UseDef first, UseDef last)
A range the range [first, last] to the interval.
bool is_pseudo() const
Is a pseudo use/def.
UseDef next_usedef_after(UseDef, UseDef) const