CACAO
LivetimeInterval.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/LivetimeInterval.hpp - 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 
25 #ifndef _JIT_COMPILER2_LIVETIMEINTERVAL
26 #define _JIT_COMPILER2_LIVETIMEINTERVAL
27 
30 
31 #include "future/memory.hpp" // for cacao::shared_ptr
32 
37 
38 #include <climits>
39 
40 MM_MAKE_NAME(UseDef)
41 MM_MAKE_NAME(LivetimeInterval)
42 MM_MAKE_NAME(LivetimeIntervalImpl)
43 
44 namespace cacao {
45 namespace jit {
46 namespace compiler2 {
47 
48 // forward declaration
49 class LivetimeIntervalImpl;
50 class BeginInst;
51 class LivetimeAnalysisPass;
52 class Register;
53 class MachineOperand;
54 class MachineOperandDesc;
55 class StackSlotManager;
56 class ManagedStackSlot;
57 class BasicBlockSchedule;
58 class MachineInstructionSchedule;
59 
60 class UseDef : public memory::ManagerMixin<UseDef> {
61 public:
62  enum Type {
63  Use,
64  Def,
66  PseudoDef
67  };
68 
69  /// constructor
70  UseDef(Type type, MIIterator it, MachineOperandDesc *op = NULL) : type(type), it(it), op(op) {
71  assert(type == PseudoUse || type == PseudoDef || op);
72  }
73  /// Is a def position
74  bool is_def() const { return type == Def; }
75  /// Is a use position
76  bool is_use() const { return type == Use; }
77  /// Is a pseudo def position
78  bool is_pseudo_def() const { return type == PseudoDef; }
79  /// Is a pseudo use position
80  bool is_pseudo_use() const { return type == PseudoUse; }
81  /// Is a pseudo use/def
82  bool is_pseudo() const { return is_pseudo_use() || is_pseudo_def(); }
83 
84 
85  /// Get instruction iterator
86  MIIterator get_iterator() const { return it; }
87  /// Get operand descriptor
88  MachineOperandDesc* get_operand() const { return op; }
89 private:
90  /// Type
92  /// Iterator pointing to the instruction
94  /// Operand
96 };
97 
98 struct LivetimeRange {
101  LivetimeRange(const UseDef &start, const UseDef &end)
102  : start(start), end(end) {}
103 };
104 
105 
106 class LivetimeInterval : public memory::ManagerMixin<LivetimeInterval> {
107 public:
109  typedef IntervalListTy::const_iterator const_iterator;
110  typedef IntervalListTy::iterator iterator;
111 
112  typedef std::multiset<UseDef> UseListTy;
113  typedef std::multiset<UseDef> DefListTy;
114  typedef UseListTy::const_iterator const_use_iterator;
115  typedef DefListTy::const_iterator const_def_iterator;
116  typedef UseListTy::iterator use_iterator;
117  typedef DefListTy::iterator def_iterator;
118 
119  enum State {
120  Unhandled, ///< Interval no yet started
121  Active, ///< Interval is live
122  Inactive, ///< Interval is inactive
123  Handled ///< Interval is finished
124  };
125  /// constructor
126  explicit LivetimeInterval(MachineOperand*);
127  /// copy constructor
128  LivetimeInterval(const LivetimeInterval &other);
129  /// copy assignment operator
130  LivetimeInterval& operator=(const LivetimeInterval &other);
131 
132  /// A range the range [first, last] to the interval
133  void add_range(UseDef first, UseDef last);
134  /// Set from. If no interval available add range from to.
135  void set_from(UseDef from, UseDef to);
136  State get_State(MIIterator pos) const;
137  State get_State(UseDef pos) const;
138  /// Is use position
139  bool is_use_at(MIIterator pos) const;
140  /// Is def position
141  bool is_def_at(MIIterator pos) const;
142  /// Get the current store of the interval
143  MachineOperand* get_operand() const;
144  /// Get the store of the interval at position pos
145  MachineOperand* get_operand(MIIterator pos) const;
146  /// Set the current store of the interval
147  void set_operand(MachineOperand* op);
148  /// Get the hint for the interval
149  MachineOperand* get_hint() const;
150  /// Set the hit for the interval
151  void set_hint(MachineOperand* op);
152  /**
153  * Get the initial operand. This is needed to identify phi instructions
154  * as they do not have an MIIterator associated with them.
155  */
156  MachineOperand* get_init_operand() const;
157 
158  /**
159  * Split interval at active pos.
160  * @param pos Must be a move/copy instruction with one input and one output
161  * @param current move UseDef's after current. If NULL, move UseDef's after pos
162  */
163  LivetimeInterval split_active(MIIterator pos, UseDef *current = NULL);
164  /**
165  * Split interval at inactive pos.
166  */
167  LivetimeInterval split_inactive(UseDef pos, MachineOperand* MO);
168  /**
169  * Split a phi input operand
170  */
171  LivetimeInterval split_phi_active(MIIterator pos, MachineOperand* MO);
172 
173  /// get next use def after pos (if not found return end)
174  UseDef next_usedef_after(UseDef pos, UseDef end) const;
175 
176  /// get next split interval
177  LivetimeInterval get_next() const;
178  bool has_next() const;
179 
180  const_iterator begin() const;
181  const_iterator end() const;
182  std::size_t size() const;
183  bool empty() const;
184  LivetimeRange front() const;
185  LivetimeRange back() const;
186 
187  // uses
188  const_use_iterator use_begin() const;
189  const_use_iterator use_end() const;
190  std::size_t use_size() const;
191  // defs
192  const_def_iterator def_begin() const;
193  const_def_iterator def_end() const;
194  std::size_t def_size() const;
195 private:
196  shared_ptr<LivetimeIntervalImpl> pimpl;
197  friend class LivetimeIntervalImpl;
198 };
199 
200 class LivetimeIntervalImpl : public memory::ManagerMixin<LivetimeIntervalImpl> {
201 public:
205 
207 /**
208  * TODO: doc me!
209  */
210 
211  /**
212  * @Cpp11 this could be changed to std::set where erase returns an
213  * iterator.
214  */
215  typedef std::multiset<UseDef> UseListTy;
216  typedef std::multiset<UseDef> DefListTy;
217  typedef UseListTy::const_iterator const_use_iterator;
218  typedef DefListTy::const_iterator const_def_iterator;
219  typedef UseListTy::iterator use_iterator;
220  typedef DefListTy::iterator def_iterator;
221 private:
225  MachineOperand* operand; ///< store for the interval
226  MachineOperand* init_operand; ///< initial operand for the interval
227  MachineOperand* hint; ///< hint for the interval
229 
230  void insert_usedef(const UseDef &usedef) {
231  if (usedef.is_use())
232  uses.insert(usedef);
233  if (usedef.is_def())
234  defs.insert(usedef);
235  }
236  static void move_use_def(LivetimeIntervalImpl *from, LivetimeIntervalImpl *to, UseDef pos);
237 public:
238  /// construtor
239  LivetimeIntervalImpl(MachineOperand* op): operand(op), init_operand(op), hint(NULL), next(NULL) {}
240  /**
241  * A range the range [first, last] to the interval
242  */
243  void add_range(UseDef first, UseDef last);
244  void set_from(UseDef from, UseDef to);
245  State get_State(MIIterator pos) const;
246  State get_State(UseDef pos) const;
247  bool is_use_at(MIIterator pos) const;
248  bool is_def_at(MIIterator pos) const;
249  MachineOperand* get_operand() const { return operand; }
250  void set_operand(MachineOperand* op) { operand = op; }
251  MachineOperand* get_init_operand() const { return init_operand; }
252  MachineOperand* get_hint() const { return hint; }
253  void set_hint(MachineOperand* op) { hint = op; }
254  LivetimeInterval get_next() const { assert(has_next()); return *next; }
255  bool has_next() const { return bool(next); }
256  LivetimeInterval split_active(MIIterator pos, UseDef *current = NULL);
257  LivetimeInterval split_inactive(UseDef pos, MachineOperand* MO);
258  LivetimeInterval split_phi_active(MIIterator pos, MachineOperand* MO);
259 
260  MachineOperand* get_operand(MIIterator pos) const;
261  UseDef next_usedef_after(UseDef,UseDef) const;
262 
263  const_iterator begin() const { return intervals.begin(); }
264  const_iterator end() const { return intervals.end(); }
265  std::size_t size() const { return intervals.size(); }
266  bool empty() const { return intervals.empty(); }
267  LivetimeRange front() const { return intervals.front(); }
268  LivetimeRange back() const { return intervals.back(); }
269 
270  const_use_iterator use_begin() const { return uses.begin(); }
271  const_use_iterator use_end() const { return uses.end(); }
272  std::size_t use_size() const { return uses.size(); }
273 
274  const_def_iterator def_begin() const { return defs.begin(); }
275  const_def_iterator def_end() const { return defs.end(); }
276  std::size_t def_size() const { return defs.size(); }
277 };
278 
279 // LivetimeInterval
280 
281 inline LivetimeInterval::LivetimeInterval(MachineOperand* op) : pimpl(new LivetimeIntervalImpl(op)){}
282 inline LivetimeInterval::LivetimeInterval(const LivetimeInterval &other) : pimpl(other.pimpl) {}
284  pimpl = other.pimpl;
285  return *this;
286 }
287 inline void LivetimeInterval::add_range(UseDef first, UseDef last) {
288  pimpl->add_range(first, last);
289 }
291  pimpl->set_from(from, to);
292 }
294  return pimpl->get_State(pos);
295 }
297  return pimpl->get_State(pos);
298 }
300  return pimpl->is_use_at(pos);
301 }
303  return pimpl->is_def_at(pos);
304 }
305 
307  return pimpl->begin();
308 }
310  return pimpl->end();
311 }
312 inline std::size_t LivetimeInterval::size() const {
313  return pimpl->size();
314 }
315 inline bool LivetimeInterval::empty() const {
316  return pimpl->empty();
317 }
319  return pimpl->front();
320 }
322  return pimpl->back();
323 }
325  return pimpl->get_operand();
326 }
328  return pimpl->get_operand(pos);
329 }
331  return pimpl->get_init_operand();
332 }
334  pimpl->set_operand(op);
335 }
337  return pimpl->get_hint();
338 }
340  pimpl->set_hint(op);
341 }
343  return pimpl->next_usedef_after(pos,end);
344 }
346  return pimpl->split_active(pos, current);
347 }
349  return pimpl->split_inactive(pos, MO);
350 }
352  return pimpl->split_phi_active(pos, MO);
353 }
355  return pimpl->get_next();
356 }
357 inline bool LivetimeInterval::has_next() const {
358  return pimpl->has_next();
359 }
360 
361 // uses
363  return pimpl->use_begin();
364 }
366  return pimpl->use_end();
367 }
368 inline std::size_t LivetimeInterval::use_size() const {
369  return pimpl->use_size();
370 }
371 // defs
373  return pimpl->def_begin();
374 }
376  return pimpl->def_end();
377 }
378 inline std::size_t LivetimeInterval::def_size() const {
379  return pimpl->def_size();
380 }
381 
383  const LivetimeInterval &b, UseDef pos, UseDef end);
384 
385 /// less then operator
386 inline bool operator<(const UseDef& lhs,const UseDef& rhs) {
387  if (lhs.get_iterator() < rhs.get_iterator() )
388  return true;
389  if (rhs.get_iterator() < lhs.get_iterator() )
390  return false;
391  // iterators are equal
392  if ( (lhs.is_use() || lhs.is_pseudo_use() ) && (rhs.is_def() || rhs.is_pseudo_def() ) )
393  return true;
394  return false;
395 }
396 
397 inline bool operator!=(const UseDef& lhs,const UseDef& rhs) {
398  return (lhs < rhs || rhs < lhs);
399 }
400 inline bool operator==(const UseDef& lhs,const UseDef& rhs) {
401  return !(lhs != rhs);
402 }
403 inline bool operator<=(const UseDef& lhs,const UseDef& rhs) {
404  return lhs < rhs || lhs == rhs;
405 }
406 
407 OStream& operator<<(OStream &OS, const LivetimeInterval &lti);
408 OStream& operator<<(OStream &OS, const LivetimeInterval *lti);
409 
410 OStream& operator<<(OStream &OS, const UseDef &usedef);
411 OStream& operator<<(OStream &OS, const LivetimeRange &range);
412 
413 } // end namespace compiler2
414 } // end namespace jit
415 } // end namespace cacao
416 
417 #endif /* _JIT_COMPILER2_LIVETIMEINTERVAL */
418 
419 
420 /*
421  * These are local overrides for various environment variables in Emacs.
422  * Please do not remove this and leave it at the end of the file, where
423  * Emacs will automagically detect them.
424  * ---------------------------------------------------------------------
425  * Local variables:
426  * mode: c++
427  * indent-tabs-mode: t
428  * c-basic-offset: 4
429  * tab-width: 4
430  * End:
431  * vim:noexpandtab:sw=4:ts=4:
432  */
void add_range(UseDef first, UseDef last)
A range the range [first, last] to the interval.
MIIterator get_iterator() const
Get instruction iterator.
UseListTy::const_iterator const_use_iterator
LivetimeInterval::const_iterator const_iterator
argument_type from
LivetimeInterval split_inactive(UseDef pos, MachineOperand *MO)
Split interval at inactive pos.
u2 op
Definition: disass.cpp:129
Custom new/delete handler mixin.
Definition: Manager.hpp:43
void set_from(UseDef from, UseDef to)
Set from. If no interval available add range from to.
#define MM_MAKE_NAME(x)
Definition: memstats.hpp:127
alloc::list< LivetimeRange >::type IntervalListTy
UseDef(Type type, MIIterator it, MachineOperandDesc *op=NULL)
constructor
State get_State(MIIterator pos) const
Descriptor of a MachineOperand.
bool is_pseudo_use() const
Is a pseudo use position.
LivetimeInterval split_active(MIIterator pos, UseDef *current=NULL)
Split interval at active pos.
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
MachineBasicBlock * current
std::list< T, Allocator< T > > type
Definition: list.hpp:38
std::multiset< UseDef > UseListTy
TODO: doc me!
UseDef next_usedef_after(UseDef pos, UseDef end) const
get next use def after pos (if not found return end)
LivetimeInterval split_phi_active(MIIterator pos, MachineOperand *MO)
Split a phi input operand.
void set_operand(MachineOperand *op)
Set the current store of the interval.
MachineOperand * operand
store for the interval
Simple stream class for formatted output.
Definition: OStream.hpp:141
OStream & operator<<(OStream &OS, const Conditional::CondID &cond)
Definition: Conditional.cpp:34
bool is_pseudo_def() const
Is a pseudo def position.
bool operator!=(const UseDef &lhs, const UseDef &rhs)
MIIterator pos
OStream & OS
bool is_use() const
Is a use position.
bool operator==(const UseDef &lhs, const UseDef &rhs)
MachineOperandDesc * get_operand() const
Get operand descriptor.
LivetimeInterval & operator=(const LivetimeInterval &other)
copy assignment operator
MIIterator it
Iterator pointing to the instruction.
MachineOperand * get_init_operand() const
Get the initial operand.
UseDef next_intersection(const LivetimeInterval &a, const LivetimeInterval &b, UseDef pos, UseDef end)
LivetimeIntervalImpl(MachineOperand *op)
construtor
MachineOperand * hint
hint for the interval
IntervalListTy::const_iterator const_iterator
Operands that can be directly used by the machine (register, memory, stackslot)
bool operator<(const Edge &lhs, const Edge &rhs)
MachineOperand * get_operand() const
Get the current store of the interval.
MachineOperandDesc * op
Operand.
bool is_use_at(MIIterator pos) const
Is use position.
LivetimeRange(const UseDef &start, const UseDef &end)
MachineOperand * get_hint() const
Get the hint for the interval.
static java_object_t * next
Definition: copy.c:43
LivetimeInterval::IntervalListTy IntervalListTy
shared_ptr< LivetimeIntervalImpl > pimpl
bool is_def() const
Is a def position.
bool is_def_at(MIIterator pos) const
Is def position.
LivetimeInterval get_next() const
get next split interval
void set_hint(MachineOperand *op)
Set the hit for the interval.
bool operator<=(const UseDef &lhs, const UseDef &rhs)
LivetimeInterval(MachineOperand *)
constructor
MachineOperand * init_operand
initial operand for the interval
bool is_pseudo() const
Is a pseudo use/def.
DefListTy::const_iterator const_def_iterator