GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
jit-ir.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2018 Max Brister
4 
5 This file is part of Octave.
6 
7 Octave is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with Octave; see the file COPYING. If not, see
19 <https://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Author: Max Brister <max@2bass.com>
24 
25 // defines required by llvm
26 #define __STDC_LIMIT_MACROS
27 #define __STDC_CONSTANT_MACROS
28 
29 #if defined (HAVE_CONFIG_H)
30 # include "config.h"
31 #endif
32 
33 #if defined (HAVE_LLVM)
34 
35 #include "jit-ir.h"
36 
37 #if defined (HAVE_LLVM_IR_FUNCTION_H)
38 # include <llvm/IR/BasicBlock.h>
39 # include <llvm/IR/Instructions.h>
40 #else
41 # include <llvm/BasicBlock.h>
42 # include <llvm/Instructions.h>
43 #endif
44 
45 #include "error.h"
46 
47 namespace octave
48 {
49 
50  // -------------------- jit_factory --------------------
52  {
53  for (value_list::iterator iter = m_all_values.begin ();
54  iter != m_all_values.end (); ++iter)
55  delete *iter;
56  }
57 
58  void
60  {
61  if (value->type ())
62  m_constants.push_back (value);
63  m_all_values.push_back (value);
64  }
65 
66  // -------------------- jit_block_list --------------------
67  void
69  {
70  ++iter;
71  insert_before (iter, ablock);
72  }
73 
74  void
76  {
77  insert_after (loc->location (), ablock);
78  }
79 
80  void
82  {
83  iter = m_list.insert (iter, ablock);
84  ablock->stash_location (iter);
85  }
86 
87  void
89  {
90  insert_before (loc->location (), ablock);
91  }
92 
93  void
95  {
96  if (m_list.size ())
97  {
98  jit_block *block = m_list.back ();
99  block->label ();
100  }
101  }
102 
103  std::ostream&
104  jit_block_list::print (std::ostream& os, const std::string& header) const
105  {
106  os << "-------------------- " << header << " --------------------\n";
107  return os << *this;
108  }
109 
110  std::ostream&
111  jit_block_list::print_dom (std::ostream& os) const
112  {
113  os << "-------------------- dom info --------------------\n";
114  for (const_iterator iter = begin (); iter != end (); ++iter)
115  {
116  assert (*iter);
117  (*iter)->print_dom (os);
118  }
119  os << std::endl;
120 
121  return os;
122  }
123 
124  void
126  {
127  m_list.push_back (b);
128  iterator iter = m_list.end ();
129  b->stash_location (--iter);
130  }
131 
132  std::ostream&
133  operator<<(std::ostream& os, const jit_block_list& blocks)
134  {
135  for (jit_block_list::const_iterator iter = blocks.begin ();
136  iter != blocks.end (); ++iter)
137  {
138  assert (*iter);
139  (*iter)->print (os, 0);
140  }
141  return os << std::endl;
142  }
143 
144  // -------------------- jit_use --------------------
145  jit_block *
146  jit_use::user_parent (void) const
147  {
148  return m_user->parent ();
149  }
150 
151  // -------------------- jit_value --------------------
153  { }
154 
155  jit_block *
157  {
158  jit_use *use = first_use ();
159  while (use)
160  {
161  if (! isa<jit_error_check> (use->user ()))
162  return use->user_parent ();
163 
164  use = use->next ();
165  }
166 
167  return 0;
168  }
169 
170  void
172  {
173  while (first_use ())
174  {
175  jit_instruction *user = first_use ()->user ();
176  size_t idx = first_use ()->index ();
177  user->stash_argument (idx, value);
178  }
179  }
180 
181 #define JIT_METH(clname) \
182  void \
183  jit_ ## clname::accept (jit_ir_walker& walker) \
184  { \
185  walker.visit (*this); \
186  }
187 
189 #undef JIT_METH
190 
191  std::ostream&
192  operator<< (std::ostream& os, const jit_value& value)
193  {
194  return value.short_print (os);
195  }
196 
197  std::ostream&
198  jit_print (std::ostream& os, jit_value *avalue)
199  {
200  if (avalue)
201  return avalue->print (os);
202  return os << "NULL";
203  }
204 
205  // -------------------- jit_instruction --------------------
206  void
208  {
209  if (m_parent)
211  resize_arguments (0);
212  }
213 
214  llvm::BasicBlock *
216  {
217  return m_parent->to_llvm ();
218  }
219 
220  std::ostream&
221  jit_instruction::short_print (std::ostream& os) const
222  {
223  if (type ())
224  jit_print (os, type ()) << ": ";
225  return os << '#' << m_id;
226  }
227 
228  void
230  {
231  for (size_t i = start; i < end; ++i)
232  {
233  jit_value *arg = argument (i);
234  jit_variable *var = dynamic_cast<jit_variable *> (arg);
235  if (var && var->has_top ())
236  stash_argument (i, var->top ());
237  }
238  }
239 
240  // -------------------- jit_block --------------------
241  void
243  {
244  assert (isa<jit_block> (value));
245  jit_block *block = static_cast<jit_block *> (value);
246 
247  jit_value::replace_with (block);
248 
249  while (ILIST_T::first_use ())
250  {
251  jit_phi_incoming *incoming = ILIST_T::first_use ();
252  incoming->stash_value (block);
253  }
254  }
255 
256  void
258  {
260  while (node)
261  {
262  jit_phi_incoming *prev = node;
263  node = node->next ();
264 
265  if (prev->user_parent () == ablock)
266  prev->stash_value (with);
267  }
268  }
269 
270  jit_block *
272  {
273  if (successor_count () == 1 && successor (0) != this
274  && (successor (0)->use_count () == 1 || m_instructions.size () == 1))
275  {
276  jit_block *to_merge = successor (0);
277  merge (*to_merge);
278  return to_merge;
279  }
280 
281  return 0;
282  }
283 
284  void
286  {
287  // the merge block will contain a new terminator
288  jit_terminator *old_term = terminator ();
289  if (old_term)
290  old_term->remove ();
291 
292  bool was_empty = end () == begin ();
293  iterator merge_begin = end ();
294  if (! was_empty)
295  --merge_begin;
296 
297  m_instructions.splice (end (), block.m_instructions);
298  if (was_empty)
299  merge_begin = begin ();
300  else
301  ++merge_begin;
302 
303  // now merge_begin points to the start of the new instructions, we must
304  // update their parent information
305  for (iterator iter = merge_begin; iter != end (); ++iter)
306  {
307  jit_instruction *instr = *iter;
308  instr->stash_parent (this, iter);
309  }
310 
311  block.replace_with (this);
312  }
313 
316  {
317  m_instructions.push_front (instr);
318  instr->stash_parent (this, m_instructions.begin ());
319  return instr;
320  }
321 
324  {
325  // FIXME: Make this O(1)
326  for (iterator iter = begin (); iter != end (); ++iter)
327  {
328  jit_instruction *temp = *iter;
329  if (! isa<jit_phi> (temp))
330  {
331  insert_before (iter, instr);
332  return instr;
333  }
334  }
335 
336  return append (instr);
337  }
338 
339  void
341  {
342  m_instructions.push_back (instr);
343  instr->stash_parent (this, --m_instructions.end ());
344  }
345 
348  {
349  iterator iloc = m_instructions.insert (loc, instr);
350  instr->stash_parent (this, iloc);
351  return instr;
352  }
353 
356  {
357  ++loc;
358  iterator iloc = m_instructions.insert (loc, instr);
359  instr->stash_parent (this, iloc);
360  return instr;
361  }
362 
365  {
366  if (m_instructions.empty ())
367  return nullptr;
368 
369  jit_instruction *last = m_instructions.back ();
370  return dynamic_cast<jit_terminator *> (last);
371  }
372 
373  bool
375  {
376  return terminator ()->alive (asucc);
377  }
378 
379  jit_block *
380  jit_block::successor (size_t i) const
381  {
382  jit_terminator *term = terminator ();
383  return term->successor (i);
384  }
385 
386  size_t
388  {
389  jit_terminator *term = terminator ();
390  return term ? term->successor_count () : 0;
391  }
392 
393  llvm::BasicBlock *
394  jit_block::to_llvm (void) const
395  {
396  return llvm::cast<llvm::BasicBlock> (m_llvm_value);
397  }
398 
399  std::ostream&
400  jit_block::print_dom (std::ostream& os) const
401  {
402  short_print (os);
403  os << ":\n";
404  os << " m_id: " << m_id << std::endl;
405  os << " predecessors: ";
406  for (jit_use *use = first_use (); use; use = use->next ())
407  os << *use->user_parent () << ' ';
408  os << std::endl;
409 
410  os << " successors: ";
411  for (size_t i = 0; i < successor_count (); ++i)
412  os << *successor (i) << ' ';
413  os << std::endl;
414 
415  os << " m_idom: ";
416  if (m_idom)
417  os << *m_idom;
418  else
419  os << "NULL";
420  os << std::endl;
421  os << " df: ";
422  for (df_iterator iter = df_begin (); iter != df_end (); ++iter)
423  os << **iter << ' ';
424  os << std::endl;
425 
426  os << " m_dom_succ: ";
427  for (size_t i = 0; i < m_dom_succ.size (); ++i)
428  os << *m_dom_succ[i] << ' ';
429 
430  return os << std::endl;
431  }
432 
433  void
434  jit_block::compute_df (size_t avisit_count)
435  {
436  if (visited (avisit_count))
437  return;
438 
439  if (use_count () >= 2)
440  {
441  for (jit_use *use = first_use (); use; use = use->next ())
442  {
443  jit_block *runner = use->user_parent ();
444  while (runner != m_idom)
445  {
446  runner->m_df.insert (this);
447  runner = runner->m_idom;
448  }
449  }
450  }
451 
452  for (size_t i = 0; i < successor_count (); ++i)
453  successor (i)->compute_df (avisit_count);
454  }
455 
456  bool
457  jit_block::update_idom (size_t avisit_count)
458  {
459  if (visited (avisit_count) || ! use_count ())
460  return false;
461 
462  bool changed = false;
463  for (jit_use *use = first_use (); use; use = use->next ())
464  {
465  jit_block *pred = use->user_parent ();
466  changed = pred->update_idom (avisit_count) || changed;
467  }
468 
469  jit_use *use = first_use ();
470  jit_block *new_idom = use->user_parent ();
471  use = use->next ();
472 
473  for (; use; use = use->next ())
474  {
475  jit_block *pred = use->user_parent ();
476  jit_block *pidom = pred->m_idom;
477  if (pidom)
478  new_idom = idom_intersect (pidom, new_idom);
479  }
480 
481  if (m_idom != new_idom)
482  {
483  m_idom = new_idom;
484  return true;
485  }
486 
487  return changed;
488  }
489 
490  void
491  jit_block::label (size_t avisit_count, size_t& number)
492  {
493  if (visited (avisit_count))
494  return;
495 
496  for (jit_use *use = first_use (); use; use = use->next ())
497  {
498  jit_block *pred = use->user_parent ();
499  pred->label (avisit_count, number);
500  }
501 
502  m_id = number++;
503  }
504 
505  void
507  {
508  for (iterator iter = begin (); iter != end (); ++iter)
509  {
510  jit_instruction *instr = *iter;
511  instr->pop_variable ();
512  }
513  }
514 
515  std::ostream&
516  jit_block::print (std::ostream& os, size_t indent) const
517  {
518  print_indent (os, indent);
519  short_print (os) << ": %pred = ";
520  for (jit_use *use = first_use (); use; use = use->next ())
521  {
522  jit_block *pred = use->user_parent ();
523  os << *pred;
524  if (use->next ())
525  os << ", ";
526  }
527  os << std::endl;
528 
529  for (const_iterator iter = begin (); iter != end (); ++iter)
530  {
531  jit_instruction *instr = *iter;
532  instr->print (os, indent + 1) << std::endl;
533  }
534  return os;
535  }
536 
537  jit_block *
539  jit_block *asuccessor)
540  {
541  if (successor_count () > 1)
542  {
543  jit_terminator *term = terminator ();
544  size_t idx = term->successor_index (asuccessor);
545  jit_block *split = factory.create<jit_block> ("phi_split", m_visit_count);
546 
547  // place after this to ensure define before use in the blocks list
548  blocks.insert_after (this, split);
549 
550  term->stash_argument (idx, split);
551  jit_branch *br = split->append (factory.create<jit_branch> (asuccessor));
552  replace_in_phi (asuccessor, split);
553 
554  if (alive ())
555  {
556  split->mark_alive ();
557  br->infer ();
558  }
559 
560  return split;
561  }
562 
563  return this;
564  }
565 
566  void
567  jit_block::create_dom_tree (size_t avisit_count)
568  {
569  if (visited (avisit_count))
570  return;
571 
572  if (m_idom != this)
573  m_idom->m_dom_succ.push_back (this);
574 
575  for (size_t i = 0; i < successor_count (); ++i)
576  successor (i)->create_dom_tree (avisit_count);
577  }
578 
579  jit_block *
581  {
582  while (i && j && i != j)
583  {
584  while (i && i->id () > j->id ())
585  i = i->m_idom;
586 
587  while (i && j && j->id () > i->id ())
588  j = j->m_idom;
589  }
590 
591  return i ? i : j;
592  }
593 
594  // -------------------- jit_phi_incoming --------------------
595 
596  jit_block *
598  { return m_user->parent (); }
599 
600  // -------------------- jit_phi --------------------
601  bool
603  {
604  jit_block *p = parent ();
605  size_t new_idx = 0;
606  jit_value *unique = argument (1);
607 
608  for (size_t i = 0; i < argument_count (); ++i)
609  {
610  jit_block *inc = incoming (i);
611  if (inc->branch_alive (p))
612  {
613  if (unique != argument (i))
614  unique = 0;
615 
616  if (new_idx != i)
617  {
618  stash_argument (new_idx, argument (i));
619  m_incoming[new_idx].stash_value (inc);
620  }
621 
622  ++new_idx;
623  }
624  }
625 
626  if (new_idx != argument_count ())
627  {
628  resize_arguments (new_idx);
629  m_incoming.resize (new_idx);
630  }
631 
632  assert (argument_count () > 0);
633  if (unique)
634  {
635  replace_with (unique);
636  return true;
637  }
638 
639  return false;
640  }
641 
642  bool
644  {
645  jit_block *p = parent ();
646  if (! p->alive ())
647  return false;
648 
649  jit_type *infered = nullptr;
650  for (size_t i = 0; i < argument_count (); ++i)
651  {
652  jit_block *inc = incoming (i);
653  if (inc->branch_alive (p))
654  infered = jit_type_join (infered, argument_type (i));
655  }
656 
657  if (infered != type ())
658  {
659  stash_type (infered);
660  return true;
661  }
662 
663  return false;
664  }
665 
666  llvm::PHINode *
667  jit_phi::to_llvm (void) const
668  {
669  return llvm::cast<llvm::PHINode> (jit_value::to_llvm ());
670  }
671 
672  // -------------------- jit_terminator --------------------
673  size_t
674  jit_terminator::successor_index (const jit_block *asuccessor) const
675  {
676  size_t scount = successor_count ();
677  for (size_t i = 0; i < scount; ++i)
678  if (successor (i) == asuccessor)
679  return i;
680 
681  panic_impossible ();
682  }
683 
684  bool
686  {
687  if (! parent ()->alive ())
688  return false;
689 
690  bool changed = false;
691  for (size_t i = 0; i < m_alive.size (); ++i)
692  if (! m_alive[i] && check_alive (i))
693  {
694  changed = true;
695  m_alive[i] = true;
696  successor (i)->mark_alive ();
697  }
698 
699  return changed;
700  }
701 
702  llvm::TerminatorInst *
704  {
705  return llvm::cast<llvm::TerminatorInst> (jit_value::to_llvm ());
706  }
707 
708  // -------------------- jit_call --------------------
709  bool
711  {
712  if (type () && jit_typeinfo::get_release (type ()).valid ())
713  {
714  for (jit_use *use = first_use (); use; use = use->next ())
715  {
716  jit_assign *assign = dynamic_cast<jit_assign *> (use->user ());
717  if (assign && assign->artificial ())
718  return false;
719  }
720 
721  return true;
722  }
723  return false;
724  }
725 
726  bool
728  {
729  // FIXME: explain algorithm
730  for (size_t i = 0; i < argument_count (); ++i)
731  {
733  if (! m_already_infered[i])
734  return false;
735  }
736 
738  if (! infered && use_count ())
739  {
740  std::stringstream ss;
741  ss << "Missing overload in type inference for ";
742  print (ss, 0);
743  throw jit_fail_exception (ss.str ());
744  }
745 
746  if (infered != type ())
747  {
748  stash_type (infered);
749  return true;
750  }
751 
752  return false;
753  }
754 
755  // -------------------- jit_error_check --------------------
758  {
759  switch (v)
760  {
761  case var_error_state:
762  return "error_state";
763  case var_interrupt:
764  return "interrupt";
765  default:
766  panic_impossible ();
767  }
768  }
769 
770  std::ostream&
771  jit_error_check::print (std::ostream& os, size_t indent) const
772  {
773  print_indent (os, indent) << "error_check " << variable_to_string (m_variable)
774  << ", ";
775 
776  if (has_check_for ())
777  os << "<for> " << *check_for () << ", ";
778  print_successor (os << "<normal> ", 1) << ", ";
779  return print_successor (os << "<error> ", 0);
780  }
781 
782  // -------------------- jit_magic_end --------------------
784  size_t aindex, size_t acount)
785  : m_value (avalue), m_index (factory.create<jit_const_index> (aindex)),
786  m_count (factory.create<jit_const_index> (acount))
787  { }
788 
789  jit_magic_end::jit_magic_end (const std::vector<context>& full_context)
790  : m_contexts (full_context)
791  {
792  resize_arguments (m_contexts.size ());
793 
794  size_t i;
795  std::vector<context>::const_iterator iter;
796  for (iter = m_contexts.begin (), i = 0; iter != m_contexts.end (); ++iter, ++i)
797  stash_argument (i, iter->m_value);
798  }
799 
802  {
803  size_t idx;
804  for (idx = 0; idx < m_contexts.size (); ++idx)
805  {
806  jit_type *ctx_type = m_contexts[idx].m_value->type ();
807  if (! ctx_type || ctx_type->skip_paren ())
808  break;
809  }
810 
811  if (idx >= m_contexts.size ())
812  idx = 0;
813 
814  context ret = m_contexts[idx];
815  ret.m_value = argument (idx);
816  return ret;
817  }
818 
819  bool
821  {
822  jit_type *new_type = overload ().result ();
823  if (new_type != type ())
824  {
825  stash_type (new_type);
826  return true;
827  }
828 
829  return false;
830  }
831 
832  std::ostream&
833  jit_magic_end::print (std::ostream& os, size_t indent) const
834  {
835  context ctx = resolve_context ();
836  short_print (print_indent (os, indent)) << " (" << *ctx.m_value << ", ";
837  return os << *ctx.m_index << ", " << *ctx.m_count << ')';
838  }
839 
840  const jit_function&
842  {
843  const context& ctx = resolve_context ();
844  return jit_typeinfo::end (ctx.m_value, ctx.m_index, ctx.m_count);
845  }
846 
847 }
848 
849 #endif
jit_type * result(const signature_vec &types) const
Definition: jit-typeinfo.h:389
void stash_value(LIST_T *avalue)
Definition: jit-util.h:168
void insert_after(iterator iter, jit_block *ablock)
Definition: jit-ir.cc:68
llvm::BasicBlock * parent_llvm(void) const
Definition: jit-ir.cc:215
while(ischar(s=fgets(fid))) fputs(stdout
void create_dom_tree(void)
Definition: jit-ir.h:694
jit_instruction * prepend(jit_instruction *instr)
Definition: jit-ir.cc:315
instruction_list::iterator iterator
Definition: jit-ir.h:566
std::vector< jit_phi_incoming > m_incoming
Definition: jit-ir.h:1050
virtual bool needs_release(void) const
Definition: jit-ir.cc:710
jit_instruction * prepend_after_phi(jit_instruction *instr)
Definition: jit-ir.cc:323
void label(void)
Definition: jit-ir.cc:94
void stash_argument(size_t i, jit_value *arg)
Definition: jit-ir.h:397
void label(void)
Definition: jit-ir.h:668
size_t successor_index(const jit_block *asuccessor) const
Definition: jit-ir.cc:674
void mark_alive(void)
Definition: jit-ir.h:591
std::list< jit_block * > m_list
Definition: jit-ir.h:176
size_t m_visit_count
Definition: jit-ir.h:778
std::ostream & print_dom(std::ostream &os) const
Definition: jit-ir.cc:111
virtual std::ostream & print(std::ostream &os, size_t indent=0) const =0
virtual ~jit_value(void)
Definition: jit-ir.cc:152
T * append(T *instr)
Definition: jit-ir.h:606
void resize_arguments(size_t acount, jit_value *adefault=nullptr)
Definition: jit-ir.h:421
bool has_check_for(void) const
Definition: jit-ir.h:1268
void merge(jit_block &merge)
Definition: jit-ir.cc:285
bool artificial(void) const
Definition: jit-ir.h:955
void compute_df(void)
Definition: jit-ir.h:689
bool alive(const jit_block *asuccessor) const
Definition: jit-ir.h:1090
jit_block * first_use_block(void)
Definition: jit-ir.cc:156
void do_construct_ssa(size_t start, size_t end)
Definition: jit-ir.cc:229
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:1328
df_set::const_iterator df_iterator
Definition: jit-ir.h:570
for fields that display a single number
Definition: time.cc:441
void push_back(jit_block *b)
Definition: jit-ir.cc:125
jit_block * parent(void) const
Definition: jit-ir.h:453
iterator begin(void)
Definition: jit-ir.h:146
size_t id(void) const
Definition: jit-ir.h:658
std::vector< context > m_contexts
Definition: jit-ir.h:1333
jit_type * jit_type_join(jit_type *lhs, jit_type *rhs)
#define JIT_VISIT_IR_NOTEMPLATE
Definition: jit-ir.h:45
jit_terminator * terminator(void) const
Definition: jit-ir.cc:364
value_list m_all_values
Definition: jit-ir.h:127
void replace_in_phi(jit_block *ablock, jit_block *with)
Definition: jit-ir.cc:257
T * create(const Args &... args)
Definition: jit-ir.h:116
df_iterator df_begin(void) const
Definition: jit-ir.h:663
size_t argument_count(void) const
Definition: jit-ir.h:416
llvm::BasicBlock * to_llvm(void) const
Definition: jit-ir.cc:394
~jit_factory(void)
Definition: jit-ir.cc:51
llvm::Value * m_llvm_value
Definition: jit-ir.h:271
jit_block * maybe_merge()
Definition: jit-ir.cc:271
void stash_parent(jit_block *aparent, std::list< jit_instruction *>::iterator alocation)
Definition: jit-ir.h:462
std::ostream & jit_print(std::ostream &os, jit_value *avalue)
Definition: jit-ir.cc:198
var
Definition: givens.cc:88
jit_block * successor(size_t i) const
Definition: jit-ir.cc:380
std::ostream & print_indent(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:264
octave_value arg
Definition: pr-output.cc:3244
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.h:1216
NODE_T * next(void) const
Definition: jit-util.h:191
bool prune(void)
Definition: jit-ir.cc:602
virtual bool infer(void)
Definition: jit-ir.cc:820
std::list< jit_block * >::const_iterator const_iterator
Definition: jit-ir.h:142
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.cc:771
bool visited(size_t avisit_count)
Definition: jit-ir.h:749
jit_type * argument_type(size_t i) const
Definition: jit-ir.h:378
virtual void replace_with(jit_value *m_value)
Definition: jit-ir.cc:171
jit_block * user_parent(void) const
Definition: jit-ir.cc:597
virtual void pop_variable(void)
Definition: jit-ir.h:440
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.cc:221
virtual bool infer(void)
Definition: jit-ir.cc:727
std::ostream & operator<<(std::ostream &os, const jit_block_list &blocks)
Definition: jit-ir.cc:133
void stash_type(jit_type *new_type)
Definition: jit-ir.h:221
jit_call * check_for(void) const
Definition: jit-ir.h:1273
void pop_all(void)
Definition: jit-ir.cc:506
std::ostream & print_dom(std::ostream &os) const
Definition: jit-ir.cc:400
size_t successor_count(void) const
Definition: jit-ir.cc:387
#define loc(X, Y)
Definition: Screen.cpp:56
jit_value * argument(size_t i) const
Definition: jit-ir.h:367
jit_const_index * m_index
Definition: jit-ir.h:1314
void internal_append(jit_instruction *instr)
Definition: jit-ir.cc:340
iterator remove(iterator iter)
Definition: jit-ir.h:626
context resolve_context(void) const
Definition: jit-ir.cc:801
df_iterator df_end(void) const
Definition: jit-ir.h:665
jit_block * successor(size_t idx=0) const
Definition: jit-ir.h:1067
jit_type * type(void) const
Definition: jit-ir.h:209
std::list< jit_instruction * >::iterator m_location
Definition: jit-ir.h:493
jit_use * first_use(void) const
Definition: jit-ir.h:584
std::vector< jit_type * > m_already_infered
Definition: jit-ir.h:476
virtual void replace_with(jit_value *value)
Definition: jit-ir.cc:242
value_list m_constants
Definition: jit-ir.h:129
#define panic_impossible()
Definition: error.h:40
virtual bool infer(void)
Definition: jit-ir.cc:685
std::list< jit_block * >::iterator iterator
Definition: jit-ir.h:141
instruction_list m_instructions
Definition: jit-ir.h:784
static jit_block * idom_intersect(jit_block *i, jit_block *j)
Definition: jit-ir.cc:580
void track_value(jit_value *v)
Definition: jit-ir.cc:59
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.cc:833
instruction_list::const_iterator const_iterator
Definition: jit-ir.h:567
iterator begin(void)
Definition: jit-ir.h:643
static const jit_function & get_release(jit_type *type)
Definition: jit-typeinfo.h:662
jit_block * m_parent
Definition: jit-ir.h:492
static const jit_operation & end(void)
Definition: jit-typeinfo.h:722
jit_instruction * insert_after(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:355
std::ostream & print_successor(std::ostream &os, size_t idx=0) const
Definition: jit-ir.h:1079
static std::string variable_to_string(variable v)
Definition: jit-ir.cc:757
jit_type * result(void) const
Definition: jit-typeinfo.h:326
jit_block * user_parent(void) const
Definition: jit-ir.cc:146
const jit_operation & m_operation
Definition: jit-ir.h:1235
virtual std::ostream & print(std::ostream &os, size_t indent=0) const
Definition: jit-ir.cc:516
bool branch_alive(jit_block *asucc) const
Definition: jit-ir.cc:374
llvm::Value * to_llvm(void) const
Definition: jit-ir.h:251
octave::sys::time start
Definition: graphics.cc:12337
jit_block * m_idom
Definition: jit-ir.h:780
jit_instruction * insert_before(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:347
std::vector< jit_block * > m_dom_succ
Definition: jit-ir.h:782
bool skip_paren(void) const
Definition: jit-typeinfo.h:166
const jit_function & overload() const
Definition: jit-ir.cc:841
size_t successor_count(void) const
Definition: jit-ir.h:1099
llvm::PHINode * to_llvm(void) const
Definition: jit-ir.cc:667
jit_block * incoming(size_t i) const
Definition: jit-ir.h:1009
p
Definition: lu.cc:138
jit_block * maybe_split(jit_factory &factory, jit_block_list &blocks, jit_block *asuccessor)
Definition: jit-ir.cc:538
b
Definition: cellfun.cc:400
iterator end(void)
Definition: jit-ir.h:150
void insert_before(iterator iter, jit_block *ablock)
Definition: jit-ir.cc:81
for i
Definition: data.cc:5264
jit_instruction * m_user
Definition: jit-ir.h:324
jit_instruction * user(void) const
Definition: jit-ir.h:308
std::vector< bool > m_alive
Definition: jit-ir.h:1111
size_t use_count(void) const
Definition: jit-ir.h:586
std::ostream & print(std::ostream &os, const std::string &header) const
Definition: jit-ir.cc:104
bool update_idom(size_t avisit_count)
Definition: jit-ir.cc:457
virtual std::ostream & short_print(std::ostream &os) const
Definition: jit-ir.h:726
jit_const_index * m_count
Definition: jit-ir.h:1315
iterator end(void)
Definition: jit-ir.h:647
bool alive(void) const
Definition: jit-ir.h:589
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
nd group nd example For each display the value
Definition: sysdep.cc:866
llvm::TerminatorInst * to_llvm(void) const
Definition: jit-ir.cc:703
octave::stream os
Definition: file-io.cc:627
size_t index(void) const
Definition: jit-ir.h:306
virtual bool infer(void)
Definition: jit-ir.cc:643
jit_magic_end(const std::vector< context > &full_context)
Definition: jit-ir.cc:789
virtual bool check_alive(size_t) const
Definition: jit-ir.h:1107
void stash_location(std::list< jit_block *>::iterator alocation)
Definition: jit-ir.h:741