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