CACAO
MachineBasicBlock.hpp
Go to the documentation of this file.
1 /* src/vm/jit/compiler2/MachineBasicBlock.hpp - MachineBasicBlock
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_MACHINEBASICBLOCK
26 #define _JIT_COMPILER2_MACHINEBASICBLOCK
27 
31 
32 #include "future/algorithm.hpp" // for all_of, none_of
33 
34 MM_MAKE_NAME(MachineBasicBlock)
35 
36 namespace cacao {
37 
38 // forward declarations
39 class OStream;
40 
41 namespace jit {
42 namespace compiler2 {
43 
44 // forward declarations
45 class MachineInstruction;
46 class MachineInstructionSchedule;
47 class MachineOperand;
48 class MachinePhiInst;
49 class Backend;
50 
51 class MIIterator {
56  static _iterator _end();
57 public:
60  typedef _iterator::iterator_category iterator_category;
61  typedef _iterator::value_type value_type;
62  typedef _iterator::difference_type difference_type;
63 
64  /// construct end element
65  MIIterator(const block_iterator &block_it)
66  : block_it(block_it), it(_end()) {}
67  /// constructor
68  MIIterator(const block_iterator &block_it, const _iterator& it)
69  : block_it(block_it), it(it) {}
70  /// copy constructor
71  MIIterator(const MIIterator& other)
72  : block_it(other.block_it), it(other.it) {}
73  /// copy assignment operator
74  MIIterator& operator=(const MIIterator& other) {
75  block_it = other.block_it;
76  it = other.it;
77  return *this;
78  }
79  MIIterator& operator++();
80  MIIterator& operator--();
82  MIIterator tmp(*this);
83  operator++();
84  return tmp;
85  }
87  MIIterator tmp(*this);
88  operator--();
89  return tmp;
90  }
91  bool operator==(const MIIterator& rhs) const {
92  if (it == _end() && rhs.it == _end())
93  return true;
94  if (block_it == rhs.block_it)
95  return it == rhs.it;
96  return false;
97  }
98  bool operator<( const MIIterator& rhs) const {
99  if (it == _end())
100  return false;
101  if (rhs.it == _end())
102  return true;
103  if (block_it == rhs.block_it) {
104  return it < rhs.it;
105  }
106  return block_it < rhs.block_it;
107  }
108  bool operator!=(const MIIterator& rhs) const { return !(*this == rhs); }
109  bool operator>( const MIIterator& rhs) const { return rhs < *this; }
110  reference operator*() { return *it; }
111  const reference operator*() const { return *it; }
112  pointer operator->() { return &*it; }
113  const pointer operator->() const { return &*it; }
114 
115  bool is_end() const;
116 
117  friend class MachineBasicBlock;
118 };
119 
120 inline bool operator<=(const MIIterator &lhs, const MIIterator& rhs) {
121  return !(rhs < lhs);
122 }
123 inline bool operator>(const MIIterator &lhs, const MIIterator& rhs) {
124  return !(lhs <= rhs);
125 }
126 inline bool operator>=(const MIIterator &lhs, const MIIterator& rhs) {
127  return !(lhs < rhs);
128 }
129 
130 /**
131  * A basic block of (scheduled) machine instructions.
132  *
133  * A MachineBasicBlock contains an ordered collection of
134  * MachineInstructions. These MachineInstructions can be accessed via
135  * MIIterators. These "smart-iterators" are not only used for access
136  * but also for ordering MachineInstructions.
137  *
138  * Once a MachineInstruction is added, the MachineBasicBlock takes over
139  * the responsability for deleting it.
140  *
141  * @ingroup low-level-ir
142  */
143 class MachineBasicBlock : public memory::ManagerMixin<MachineBasicBlock> {
144 public:
152 
155 
157  typedef PhiListTy::const_iterator const_phi_iterator;
158 
160  typedef PredListTy::const_iterator const_pred_iterator;
161  typedef PredListTy::iterator pred_iterator;
162 
163  /// construct an empty MachineBasicBlock
165  : id(id_counter++), my_it(my_it) {};
166  /// checks if the basic block has no elements.
167  bool empty() const;
168  /// returns the number of elements
169  std::size_t size() const;
170  /// Appends the given element value to the end of the container.
171  void push_back(MachineInstruction* value);
172  /// inserts value to the beginning
173  void push_front(MachineInstruction* value);
174  /// inserts value before the element pointed to by pos
175  iterator insert_before(iterator pos, MachineInstruction* value);
176  /**
177  * inserts value before the element pointed to by pos
178  * @note for standard library compatibility.
179  */
180  iterator insert(iterator pos, MachineInstruction* value);
181  /// inserts value after the element pointed to by pos
182  iterator insert_after(iterator pos, MachineInstruction* value);
183  /// inserts elements from range [first, last) before pos
184  template<class InputIt>
185  void insert_before(iterator pos, InputIt first, InputIt last);
186  /// inserts elements from range [first, last) after pos
187  template<class InputIt>
188  void insert_after(iterator pos, InputIt first, InputIt last);
189  /// erases element
190  iterator erase(iterator pos);
191  /// erases elements
192  iterator erase(iterator first, iterator last);
193  /// returns an iterator to the beginning
194  iterator begin();
195  /// returns an iterator to the end
196  iterator end();
197  /// returns an const iterator to the beginning
198  const_iterator begin() const;
199  /// returns an const iterator to the end
200  const_iterator end() const;
201  /// returns an reverse_iterator to the beginning
202  reverse_iterator rbegin();
203  /// returns an reverse_iterator to the end
204  reverse_iterator rend();
205  /// returns an const reverse_iterator to the beginning
206  const_reverse_iterator rbegin() const;
207  /// returns an const reverse_iterator to the end
208  const_reverse_iterator rend() const;
209  /// access the first element
210  const_reference front() const;
211  /// access the last element
212  const_reference back() const;
213  /// access the first element
214  reference front();
215  /// access the last element
216  reference back();
217 
218  /// Appends the given element value to the list of phis.
219  void insert_phi(MachinePhiInst* value);
220  /// returns an const iterator to the phi instructions
221  const_phi_iterator phi_begin() const;
222  /// returns an const iterator to the phi instructions
223  const_phi_iterator phi_end() const;
224  /// returns the number of phi nodes
225  std::size_t phi_size() const;
226  /// removes all phi nodes
227  void phi_clear();
228 
229  /**
230  * Appends the given element value to the list of predecessors.
231  * @note Ensure that the PHI instructions are updated as well.
232  */
233  void insert_pred(MachineBasicBlock* value);
234  /// returns an const iterator to the predecessors
235  const_pred_iterator pred_begin() const;
236  /// returns an const iterator to the predecessors
237  const_pred_iterator pred_end() const;
238  /// returns an iterator to the predecessors
239  pred_iterator pred_begin();
240  /// returns an iterator to the predecessors
241  pred_iterator pred_end();
242  /// returns the number of predecessor nodes
243  std::size_t pred_size() const;
244  /// Get the i'th predecessor
245  MachineBasicBlock* get_predecessor(std::size_t i) const;
246  /**
247  * Get predecessor index
248  * @return the predecessor index of MBB or pred_size() if not found
249  */
250  std::size_t get_predecessor_index(MachineBasicBlock* MBB) const;
251 
252  /// get a MIIterator form a iterator
253  MIIterator convert(iterator pos);
254  /// get a MIIterator form a iterator
255  MIIterator convert(reverse_iterator pos);
256  /// returns an MIIterator to the first element
257  MIIterator mi_first();
258  /// returns an MIIterator to the last element (included)
259  MIIterator mi_last();
260  /// get self iterator
261  MBBIterator self_iterator() const;
262  /// get parent
264  /// print
265  OStream& print(OStream& OS) const;
266  /// equality operator
267  bool operator==(const MachineBasicBlock &other) const;
268 
269  /// get a iterator form a MIIterator
270  static iterator convert(MIIterator pos);
271 private:
272  /// update instruction block
273  void update(MachineInstruction *MI);
274 
275  static std::size_t id_counter;
276  std::size_t id;
278  /// empty constructor
279  MachineBasicBlock() : id(id_counter++) {}
283 
284  friend class MBBBuilder;
286 };
287 
288 inline MIIterator& MIIterator::operator++() {
289  ++it;
290  if (it == (*block_it)->end()) {
291  // end of basic block
292  ++block_it;
293  // Note: by convention MachineBasicBlock blocks are not
294  // allowed to be empty. Therefor we can safely assume
295  // that (*block_it)->begin() != (*block_it)->end().
296  if (block_it == block_it.get_parent()->end()) {
297  it = _end();
298  }
299  else {
300  it = (*block_it)->begin();
301  }
302  }
303  return *this;
304 }
305 inline MIIterator& MIIterator::operator--() {
306  if (it == _end() || it == (*block_it)->begin()) {
307  // begin of basic block
308  // XXX I think this can be removed. Iterating beyond begin
309  // is undefined.
310  if (block_it == block_it.get_parent()->begin()) {
311  return *this;
312  }
313  --block_it;
314  it = (*block_it)->end();
315  }
316  --it;
317  return *this;
318 }
319 
320 inline bool MIIterator::is_end() const {
321  return it == _end();
322 }
323 
325 
326 bool check_is_phi(MachineInstruction *value);
327 
328 inline bool MachineBasicBlock::empty() const {
329  return list.empty();
330 }
331 inline std::size_t MachineBasicBlock::size() const {
332  return list.size();
333 }
334 inline void MachineBasicBlock::push_back(MachineInstruction* value) {
335  assert(!check_is_phi(value));
336  update(value);
337  list.push_back(value);
338 }
339 inline void MachineBasicBlock::push_front(MachineInstruction* value) {
340  assert(!check_is_phi(value));
341  update(value);
342  list.push_front(value);
343 }
345  MachineInstruction* value) {
346  assert(!check_is_phi(value));
347  update(value);
348  return list.insert(pos,value);
349 }
350 inline MachineBasicBlock::iterator MachineBasicBlock::insert(iterator pos,
351  MachineInstruction* value) {
352  assert(!check_is_phi(value));
353  update(value);
354  return list.insert(pos,value);
355 }
357  MachineInstruction* value) {
358  assert(!check_is_phi(value));
359  update(value);
360  return list.insert(++pos,value);
361 }
362 template<class InputIt>
364  InputIt first, InputIt last) {
365  assert(cacao::none_of(first,last,check_is_phi));
366  list.insert(pos,first,last);
367  std::for_each(first,last,
368  std::bind1st(std::mem_fun(&MachineBasicBlock::update), this));
369 }
370 template<class InputIt>
372  InputIt first, InputIt last) {
373  assert(cacao::none_of(first,last,check_is_phi));
374  list.insert(++pos,first,last);
375  std::for_each(first,last,
376  std::bind1st(std::mem_fun(&MachineBasicBlock::update), this));
377 }
379 MachineBasicBlock::erase(iterator pos) {
380  return list.erase(pos);
381 }
383 MachineBasicBlock::erase(iterator first, iterator last) {
384  return list.erase(first,last);
385 }
386 inline MachineBasicBlock::iterator MachineBasicBlock::begin() {
387  return list.begin();
388 }
389 inline MachineBasicBlock::iterator MachineBasicBlock::end() {
390  return list.end();
391 }
392 inline MachineBasicBlock::const_iterator MachineBasicBlock::begin() const {
393  return list.begin();
394 }
395 inline MachineBasicBlock::const_iterator MachineBasicBlock::end() const {
396  return list.end();
397 }
398 inline MachineBasicBlock::reverse_iterator MachineBasicBlock::rbegin() {
399  return list.rbegin();
400 }
401 inline MachineBasicBlock::reverse_iterator MachineBasicBlock::rend() {
402  return list.rend();
403 }
404 inline MachineBasicBlock::const_reverse_iterator MachineBasicBlock::rbegin() const {
405  return list.rbegin();
406 }
407 inline MachineBasicBlock::const_reverse_iterator MachineBasicBlock::rend() const {
408  return list.rend();
409 }
410 inline MachineBasicBlock::const_reference MachineBasicBlock::front() const {
411  return list.front();
412 }
413 inline MachineBasicBlock::const_reference MachineBasicBlock::back() const {
414  return list.back();
415 }
416 inline MachineBasicBlock::reference MachineBasicBlock::front() {
417  return list.front();
418 }
419 inline MachineBasicBlock::reference MachineBasicBlock::back() {
420  return list.back();
421 }
422 inline MIIterator MachineBasicBlock::convert(iterator pos) {
423  if (pos == end()) {
424  return ++convert(--pos);
425  }
426  return MIIterator(my_it,pos);
427 }
428 inline MIIterator MachineBasicBlock::convert(reverse_iterator pos) {
429  return convert(--(pos.base()));
430 }
431 inline MachineBasicBlock::iterator MachineBasicBlock::convert(MIIterator pos) {
432  return pos.it;
433 }
434 inline MIIterator MachineBasicBlock::mi_first() {
435  assert(!empty());
436  return convert(begin());
437 }
438 inline MIIterator MachineBasicBlock::mi_last() {
439  assert(!empty());
440  return convert(--end());
441 }
442 inline MBBIterator MachineBasicBlock::self_iterator() const {
443  return my_it;
444 }
446  return my_it.get_parent();
447 }
448 
450  return MBB.print(OS);
451 }
452 inline void MachineBasicBlock::insert_phi(MachinePhiInst* value) {
453  phi.push_back(value);
454 }
455 inline MachineBasicBlock::const_phi_iterator MachineBasicBlock::phi_begin() const {
456  return phi.begin();
457 }
458 inline MachineBasicBlock::const_phi_iterator MachineBasicBlock::phi_end() const {
459  return phi.end();
460 }
461 inline std::size_t MachineBasicBlock::phi_size() const {
462  return phi.size();
463 }
464 inline void MachineBasicBlock::phi_clear() {
465  return phi.clear();
466 }
467 
468 inline void MachineBasicBlock::insert_pred(MachineBasicBlock* value) {
469  predecessors.push_back(value);
470 }
471 inline MachineBasicBlock::const_pred_iterator MachineBasicBlock::pred_begin() const {
472  return predecessors.begin();
473 }
474 inline MachineBasicBlock::const_pred_iterator MachineBasicBlock::pred_end() const {
475  return predecessors.end();
476 }
477 inline MachineBasicBlock::pred_iterator MachineBasicBlock::pred_begin() {
478  return predecessors.begin();
479 }
480 inline MachineBasicBlock::pred_iterator MachineBasicBlock::pred_end() {
481  return predecessors.end();
482 }
483 inline std::size_t MachineBasicBlock::pred_size() const {
484  return predecessors.size();
485 }
486 inline MachineBasicBlock* MachineBasicBlock::get_predecessor(std::size_t i) const {
487  assert(i < predecessors.size());
488  return predecessors[i];
489 }
490 inline std::size_t
492  std::size_t i = 0, e = pred_size();
493  for (; i < e; ++i) {
494  if (predecessors[i] == MBB) {
495  return i;
496  }
497  }
498  return i;
499 }
500 
501 inline bool MachineBasicBlock::operator==(const MachineBasicBlock &other) const {
502  //return this == &other;
503  return id == other.id;
504 }
505 
506 struct MoveEdgeFunctor : public std::unary_function<MachineInstruction*,void> {
510  : from(from), to(to) {}
511  void operator()(MachineInstruction* MI);
512 };
513 
514 /**
515  * Move instructions to another basic block.
516  *
517  * @note this also updates the predecessor list for the target basic blocks
518  * of jump instructions. Example if a JUMP to BB_target is moved from
519  * BB_from to BB_to than all occurrences of BB_from in BB_targets predecessor
520  * list are replaced with BB_to.
521  */
522 template <class InputIterator>
523 inline void move_instructions(InputIterator first, InputIterator last,
525  MoveEdgeFunctor Fn(from,to);
526  std::for_each(first,last,Fn);
527  to.insert_before(to.end(),first,last);
528  from.erase(first,last);
529 }
530 
531 MachinePhiInst* get_phi_from_operand(MachineBasicBlock *MBB,
532  MachineOperand* op);
533 
534 /// get a new basic block for a given edge
535 MachineBasicBlock* get_edge_block(MachineBasicBlock *from, MachineBasicBlock *to,
536  Backend *backend);
537 MIIterator get_edge_iterator(MachineBasicBlock *from, MachineBasicBlock *to,
538  Backend *backend);
539 /**
540  * Get an edge inserter.
541  *
542  * This may return an iterator to the end of predecessor block,
543  * if the predecessor has only one successor, an iterator to
544  * the beginning of the successor block, if the successor has
545  * only one predecessor, or else an iterator to a newly allocated
546  * block.
547  */
548 #if 0
549 std::insert_iterator<MachineBasicBlock> get_edge_inserter(
550  MachineBasicBlock *from, MachineBasicBlock *to);
551 #endif
552 
553 MIIterator insert_before(MIIterator pos, MachineInstruction* value);
554 MIIterator insert_after(MIIterator pos, MachineInstruction* value);
555 
556 } // end namespace compiler2
557 } // end namespace jit
558 } // end namespace cacao
559 
560 #endif /* _JIT_COMPILER2_MACHINEBASICBLOCK */
561 
562 
563 /*
564  * These are local overrides for various environment variables in Emacs.
565  * Please do not remove this and leave it at the end of the file, where
566  * Emacs will automagically detect them.
567  * ---------------------------------------------------------------------
568  * Local variables:
569  * mode: c++
570  * indent-tabs-mode: t
571  * c-basic-offset: 4
572  * tab-width: 4
573  * End:
574  * vim:noexpandtab:sw=4:ts=4:
575  */
alloc::ordered_list< MachineInstruction * >::type Container
std::reverse_iterator< const_iterator > const_reverse_iterator
allocator_type::const_reference const_reference
ordered const_iterator
MIIterator get_edge_iterator(MachineBasicBlock *from, MachineBasicBlock *to, Backend *backend)
bool check_is_phi(MachineInstruction *value)
iterator insert_before(iterator pos, MachineInstruction *value)
inserts value before the element pointed to by pos
argument_type from
MachinePhiInst * get_phi_from_operand(MachineBasicBlock *MBB, MachineOperand *op)
u2 op
Definition: disass.cpp:129
Custom new/delete handler mixin.
Definition: Manager.hpp:43
A basic block of (scheduled) machine instructions.
void move_instructions(InputIterator first, InputIterator last, MachineBasicBlock &from, MachineBasicBlock &to)
Move instructions to another basic block.
#define MM_MAKE_NAME(x)
Definition: memstats.hpp:127
iterator end()
returns an iterator to the end
allocator_type::const_pointer const_pointer
bool operator==(const MIIterator &rhs) const
MIIterator(const MIIterator &other)
copy constructor
MIIterator insert_before(MIIterator pos, MachineInstruction *value)
Get an edge inserter.
ordered iterator
PassInfo::IDTy id
allocator_type::reference reference
const reference operator*() const
bool operator>=(const MIIterator &lhs, const MIIterator &rhs)
std::iterator< std::bidirectional_iterator_tag, T >::pointer pointer
JNIEnv jthread jobject jclass jlong size
Definition: jvmti.h:387
std::list< T, Allocator< T > > type
Definition: list.hpp:38
PredListTy::const_iterator const_pred_iterator
MIIterator(const block_iterator &block_it, const _iterator &it)
constructor
MIIterator(const block_iterator &block_it)
construct end element
Instruction::InstID tmp[]
Definition: Matcher.cpp:55
LoopBase * get_parent() const
Definition: LoopBase.hpp:62
Container::reverse_iterator reverse_iterator
std::vector< T, Allocator< T > > type
Definition: vector.hpp:38
MIIterator & operator=(const MIIterator &other)
copy assignment operator
_iterator::difference_type difference_type
Simple stream class for formatted output.
Definition: OStream.hpp:141
Container::const_reverse_iterator const_reverse_iterator
MachineBasicBlock(const MBBIterator &my_it)
construct an empty MachineBasicBlock
MachineBasicBlock * get_edge_block(MachineBasicBlock *from, MachineBasicBlock *to, Backend *backend)
get a new basic block for a given edge
MIIterator i
alloc::ordered_list< MachineInstruction * >::type::iterator _iterator
bool none_of(InputIt first, InputIt last, UnaryPredicate p)
Definition: algorithm.hpp:72
MIIterator pos
allocator_type::pointer pointer
OStream & OS
bool operator!=(const MIIterator &rhs) const
bool operator<(const MIIterator &rhs) const
OStream & operator<<(OStream &OS, const std::string &t)
Definition: OStream.hpp:459
static unsigned get_predecessor_index(basicblock *from, basicblock *to)
Definition: ssa2.cpp:480
MIIterator e
bool operator==(const ordered_list< T, Allocator > &lhs, const ordered_list< T, Allocator > &rhs)
equality
Proxy to encode explicit and implicit successors.
std::reverse_iterator< iterator > reverse_iterator
OStream & print(OStream &OS) const
print
bool operator>(const MIIterator &lhs, const MIIterator &rhs)
MoveEdgeFunctor(MachineBasicBlock &from, MachineBasicBlock &to)
MIIterator insert_after(MIIterator pos, MachineInstruction *value)
alloc::vector< MachineBasicBlock * >::type PredListTy
bool operator>(const MIIterator &rhs) const
alloc::list< MachinePhiInst * >::type PhiListTy
bool operator<=(const UseDef &lhs, const UseDef &rhs)
std::iterator< std::bidirectional_iterator_tag, T >::reference reference
_iterator::iterator_category iterator_category
iterator erase(iterator pos)
erases element
An ordered_list is an indexed sequence container.