GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
pt-jit.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2012-2017 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 the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 Octave is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 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 <http://www.gnu.org/licenses/>.
20 
21 */
22 
23 // Author: Max Brister <max@2bass.com>
24 
25 #define __STDC_LIMIT_MACROS
26 #define __STDC_CONSTANT_MACROS
27 
28 #if defined (HAVE_CONFIG_H)
29 # include "config.h"
30 #endif
31 
32 #include "debug.h"
33 #include "defun.h"
34 #include "errwarn.h"
35 #include "ov.h"
36 #include "pt-all.h"
37 #include "pt-jit.h"
38 #include "sighandlers.h"
39 #include "symtab.h"
40 #include "variables.h"
41 
42 #if defined (HAVE_LLVM)
43 
44 static bool Vdebug_jit = false;
45 
46 static bool Vjit_enable = false;
47 
48 static int Vjit_startcnt = 1000;
49 
50 static int Vjit_failcnt = 0;
51 
52 #include <llvm/Analysis/CallGraph.h>
53 #include <llvm/Analysis/Passes.h>
54 
55 #if defined (HAVE_LLVM_IR_VERIFIER_H)
56 # include <llvm/IR/Verifier.h>
57 #else
58 # include <llvm/Analysis/Verifier.h>
59 #endif
60 
61 #include <llvm/Bitcode/ReaderWriter.h>
62 #include <llvm/ExecutionEngine/ExecutionEngine.h>
63 #include <llvm/ExecutionEngine/JIT.h>
64 
65 #if defined (LEGACY_PASSMANAGER)
66 # include <llvm/IR/LegacyPassManager.h>
67 #else
68 # include <llvm/PassManager.h>
69 #endif
70 
71 #if defined (HAVE_LLVM_IR_FUNCTION_H)
72 # include <llvm/IR/LLVMContext.h>
73 # include <llvm/IR/Module.h>
74 #else
75 # include <llvm/LLVMContext.h>
76 # include <llvm/Module.h>
77 #endif
78 
79 #if defined (HAVE_LLVM_SUPPORT_IRBUILDER_H)
80 # include <llvm/Support/IRBuilder.h>
81 #elif defined(HAVE_LLVM_IR_IRBUILDER_H)
82 # include <llvm/IR/IRBuilder.h>
83 #else
84 # include <llvm/IRBuilder.h>
85 #endif
86 
87 #include <llvm/Support/raw_os_ostream.h>
88 #include <llvm/Support/TargetSelect.h>
89 
90 #if defined (HAVE_LLVM_IR_DATALAYOUT_H)
91 # include <llvm/IR/DataLayout.h>
92 #elif defined(HAVE_LLVM_DATALAYOUT_H)
93 # include <llvm/DataLayout.h>
94 #else
95 # include <llvm/Target/TargetData.h>
96 #endif
97 
98 #include <llvm/Transforms/IPO.h>
99 #include <llvm/Transforms/Scalar.h>
100 
101 static llvm::IRBuilder<> builder (llvm::getGlobalContext ());
102 
103 static llvm::LLVMContext& context = llvm::getGlobalContext ();
104 
105 // -------------------- jit_break_exception --------------------
106 
107 // jit_break is thrown whenever a branch we are converting has only breaks or
108 // continues. This is because all code that follows a break or continue
109 // is dead.
110 class jit_break_exception : public std::exception
111 { };
112 
113 // -------------------- jit_convert --------------------
115  : converting_function (false)
116 {
118 
119  if (for_bounds)
120  create_variable (next_for_bounds (false), for_bounds);
121 
122  try
123  {
124  visit (tee);
125  }
126  catch (const jit_break_exception&)
127  { }
128 
129  // breaks must have been handled by the top level loop
130  assert (breaks.empty ());
131  assert (continues.empty ());
132 
135 
136  for (variable_map::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
137  {
138  jit_variable *var = iter->second;
139  const std::string& name = var->name ();
140  if (name.size () && name[0] != '#')
142  }
143 
145 }
146 
148  const std::vector<jit_type *>& args)
149  : converting_function (true)
150 {
151  initialize (fcn.scope ());
152 
153  tree_parameter_list *plist = fcn.parameter_list ();
154  tree_parameter_list *rlist = fcn.return_list ();
155  if (plist && plist->takes_varargs ())
156  throw jit_fail_exception ("varags not supported");
157 
158  if (rlist && (rlist->size () > 1 || rlist->takes_varargs ()))
159  throw jit_fail_exception ("multiple returns not supported");
160 
161  if (plist)
162  {
163  tree_parameter_list::iterator piter = plist->begin ();
164  for (size_t i = 0; i < args.size (); ++i, ++piter)
165  {
166  if (piter == plist->end ())
167  throw jit_fail_exception ("Too many parameter to function");
168 
169  tree_decl_elt *elt = *piter;
170  std::string name = elt->name ();
171  create_variable (name, args[i]);
172  }
173  }
174 
175  jit_value *return_value = 0;
176  bool all_breaking = false;
177  if (fcn.is_special_expr ())
178  {
179  tree_expression *expr = fcn.special_expr ();
180  if (expr)
181  {
182  jit_variable *retvar = get_variable ("#return");
183  jit_value *retval = 0;
184  try
185  {
186  retval = visit (expr);
187  }
188  catch (const jit_break_exception&)
189  { }
190 
191  if (breaks.size () || continues.size ())
192  throw jit_fail_exception ("break/continue not supported in "
193  "anonymous functions");
194 
195  block->append (factory.create<jit_assign> (retvar, retval));
196  return_value = retvar;
197  }
198  }
199  else
200  {
201  try
202  {
203  visit_statement_list (*fcn.body ());
204  }
205  catch (const jit_break_exception&)
206  {
207  all_breaking = true;
208  }
209 
210  // the user may use break or continue to exit the function
213  }
214 
215  if (! all_breaking)
217 
219  block = final_block;
220 
221  if (! return_value && rlist && rlist->size () == 1)
222  {
223  tree_decl_elt *elt = rlist->front ();
224  return_value = get_variable (elt->name ());
225  }
226 
227  // FIXME: We should use live range analysis to delete variables where needed.
228  // For now we just delete everything at the end of the function.
229  for (variable_map::iterator iter = vmap.begin (); iter != vmap.end (); ++iter)
230  {
231  if (iter->second != return_value)
232  {
233  jit_call *call;
235  iter->second);
236  final_block->append (call);
237  }
238  }
239 
240  if (return_value)
241  final_block->append (factory.create<jit_return> (return_value));
242  else
244 }
245 
246 void
248 {
249  throw jit_fail_exception ("No visit_anon_fcn_handle implementation");
250 }
251 
252 void
254 {
255  throw jit_fail_exception ("No visit_argument_list implementation");
256 }
257 
258 void
260 {
262  {
264  boole = dynamic_cast<tree_boolean_expression *> (&be);
265  assert (boole);
266  bool is_and = boole->op_type () == tree_boolean_expression::bool_and;
267 
268  std::string short_name = next_shortcircut_result ();
269  jit_variable *short_result = factory.create<jit_variable> (short_name);
270  vmap[short_name] = short_result;
271 
273  tree_expression *lhs = be.lhs ();
274  jit_value *lhsv = visit (lhs);
276 
277  jit_block *short_early = factory.create<jit_block> ("short_early");
278  blocks.push_back (short_early);
279 
280  jit_block *short_cont = factory.create<jit_block> ("short_cont");
281 
282  if (is_and)
283  block->append (factory.create<jit_cond_branch> (lhsv, short_cont,
284  short_early));
285  else
286  block->append (factory.create<jit_cond_branch> (lhsv, short_early,
287  short_cont));
288 
289  block = short_early;
290 
291  jit_value *early_result = factory.create<jit_const_bool> (! is_and);
292  block->append (factory.create<jit_assign> (short_result, early_result));
293  block->append (factory.create<jit_branch> (done));
294 
295  blocks.push_back (short_cont);
296  block = short_cont;
297 
298  tree_expression *rhs = be.rhs ();
299  jit_value *rhsv = visit (rhs);
301  block->append (factory.create<jit_assign> (short_result, rhsv));
302  block->append (factory.create<jit_branch> (done));
303 
304  blocks.push_back (done);
305  block = done;
306  result = short_result;
307  }
308  else
309  {
310  tree_expression *lhs = be.lhs ();
311  jit_value *lhsv = visit (lhs);
312 
313  tree_expression *rhs = be.rhs ();
314  jit_value *rhsv = visit (rhs);
315 
316  const jit_operation& fn = jit_typeinfo::binary_op (be.op_type ());
317  result = create_checked (fn, lhsv, rhsv);
318  }
319 }
320 
321 void
323 {
324  breaks.push_back (block);
325  throw jit_break_exception ();
326 }
327 
328 void
330 {
331  // in the futher we need to add support for classes and deal with rvalues
332  jit_value *base = visit (expr.base ());
333  jit_value *limit = visit (expr.limit ());
334  jit_value *increment;
335  tree_expression *tinc = expr.increment ();
336 
337  if (tinc)
338  increment = visit (tinc);
339  else
340  increment = factory.create<jit_const_scalar> (1);
341 
343  base, limit, increment));
344 }
345 
346 void
348 {
349  continues.push_back (block);
350  throw jit_break_exception ();
351 }
352 
353 void
355 {
356  throw jit_fail_exception ("No visit_global_command implemenation");
357 }
358 
359 void
361 {
362  throw jit_fail_exception ("No visit_persistent_command implementation");
363 }
364 
365 void
367 {
368  throw jit_fail_exception ("No visit_decl_elt implementation");
369 }
370 
371 void
373 {
374  throw jit_fail_exception ("No visit_decl_init_list implementation");
375 }
376 
377 void
379 {
380  // Note we do an initial check to see if the loop will run atleast once.
381  // This allows us to get better type inference bounds on variables defined
382  // and used only inside the for loop (e.g., the index variable)
383 
384  // If we are a nested for loop we need to store the previous breaks
386  frame.protect_var (breaks);
387  frame.protect_var (continues);
388  breaks.clear ();
389  continues.clear ();
390 
391  // we need a variable for our iterator, because it is used in multiple blocks
392  std::string iter_name = next_iterator ();
393  jit_variable *iterator = factory.create<jit_variable> (iter_name);
394  factory.create<jit_variable> (iter_name);
395  vmap[iter_name] = iterator;
396 
397  jit_block *body = factory.create<jit_block> ("for_body");
398  jit_block *tail = factory.create<jit_block> ("for_tail");
399 
400  // do control expression, iter init, and condition check in prev_block (block)
401  // if we are the top level for loop, the bounds is an input argument.
402  jit_value *control = find_variable (next_for_bounds ());
403  if (! control)
404  control = visit (cmd.control_expr ());
406  control);
407  block->append (init_iter);
408  block->append (factory.create<jit_assign> (iterator, init_iter));
409 
411  iterator);
412  block->append (check);
413  block->append (factory.create<jit_cond_branch> (check, body, tail));
414 
415  blocks.push_back (body);
416  block = body;
417 
418  // compute the syntactical iterator
420  control, iterator);
421  block->append (idx_rhs);
422  do_assign (cmd.left_hand_side (), idx_rhs);
423 
424  // do loop
425  tree_statement_list *pt_body = cmd.body ();
426  bool all_breaking = false;
427  try
428  {
429  pt_body->accept (*this);
430  }
431  catch (const jit_break_exception&)
432  {
433  if (continues.empty ())
434  {
435  // WTF are you doing user? Every branch was a break, why did you have
436  // a loop??? Users are silly people...
437  finish_breaks (tail, breaks);
438  blocks.push_back (tail);
439  block = tail;
440  return;
441  }
442 
443  all_breaking = true;
444  }
445 
446  // check our condition, continues jump to this block
447  jit_block *check_block = factory.create<jit_block> ("for_check");
448  blocks.push_back (check_block);
449 
450  jit_block *interrupt_check = factory.create<jit_block> ("for_interrupt");
451  blocks.push_back (interrupt_check);
452 
453  if (! all_breaking)
454  block->append (factory.create<jit_branch> (check_block));
455  finish_breaks (check_block, continues);
456 
457  block = check_block;
460  jit_call *iter_inc = factory.create<jit_call> (add_fn, iterator, one);
461  block->append (iter_inc);
462  block->append (factory.create<jit_assign> (iterator, iter_inc));
463  check = block->append (factory.create<jit_call> (jit_typeinfo::for_check,
464  control, iterator));
465  block->append (factory.create<jit_cond_branch> (check, interrupt_check,
466  tail));
467 
468  block = interrupt_check;
469  jit_error_check *ec
471  body, final_block);
472  block->append (ec);
473 
474  // breaks will go to our tail
475  blocks.push_back (tail);
476  finish_breaks (tail, breaks);
477  block = tail;
478 }
479 
480 void
482 {
483  throw jit_fail_exception ("No visit_complex_for_command implementation");
484 }
485 
486 void
488 {
489  throw jit_fail_exception ("No visit_octave_user_script implementation");
490 }
491 
492 void
494 {
495  throw jit_fail_exception ("No visit_octave_user_function implementation");
496 }
497 
498 void
500 {
501  throw jit_fail_exception ("No visit_octave_user_function_header implementation");
502 }
503 
504 void
506 {
507  throw jit_fail_exception ("No visit_octave_user_function_trailer implementation");
508 }
509 
510 void
512 {
513  throw jit_fail_exception ("No visit_function_def implementation");
514 }
515 
516 void
518 {
519  if (ti.has_magic_end ())
520  {
521  if (! end_context.size ())
522  throw jit_fail_exception ("Illegal end");
524  }
525  else
526  {
527  jit_variable *var = get_variable (ti.name ());
528  jit_instruction *instr;
530  result = block->append (instr);
531  }
532 }
533 
534 void
536 {
537  throw jit_fail_exception ("No visit_if_clause implementation");
538 }
539 
540 void
542 {
543  tree_if_command_list *lst = cmd.cmd_list ();
544  assert (lst); // jwe: Can this be null?
545  lst->accept (*this);
546 }
547 
548 void
550 {
551  tree_if_clause *last = lst.back ();
552  size_t last_else = static_cast<size_t> (last->is_else_clause ());
553 
554  // entry_blocks represents the block you need to enter in order to execute
555  // the condition check for the ith clause. For the else, it is simple the
556  // else body. If there is no else body, then it is padded with the tail.
557  std::vector<jit_block *> entry_blocks (lst.size () + 1 - last_else);
558  entry_blocks[0] = block;
559 
560  // we need to construct blocks first, because they have jumps to each other.
562  ++iter;
563  for (size_t i = 1; iter != lst.end (); ++iter, ++i)
564  {
565  tree_if_clause *tic = *iter;
566  if (tic->is_else_clause ())
567  entry_blocks[i] = factory.create<jit_block> ("else");
568  else
569  entry_blocks[i] = factory.create<jit_block> ("ifelse_cond");
570  }
571 
572  jit_block *tail = factory.create<jit_block> ("if_tail");
573  if (! last_else)
574  entry_blocks[entry_blocks.size () - 1] = tail;
575 
576  // each branch in the if statement will have different breaks/continues
577  block_list current_breaks = breaks;
578  block_list current_continues = continues;
579  breaks.clear ();
580  continues.clear ();
581 
582  size_t num_incomming = 0; // number of incomming blocks to our tail
583  iter = lst.begin ();
584  for (size_t i = 0; iter != lst.end (); ++iter, ++i)
585  {
586  tree_if_clause *tic = *iter;
587  block = entry_blocks[i];
588  assert (block);
589 
590  if (i) // the first block is prev_block, so it has already been added
591  blocks.push_back (entry_blocks[i]);
592 
593  if (! tic->is_else_clause ())
594  {
595  tree_expression *expr = tic->condition ();
596  jit_value *cond = visit (expr);
598  cond);
599  jit_block *body = factory.create<jit_block> (i == 0 ? "if_body"
600  : "ifelse_body");
601  blocks.push_back (body);
602 
603  jit_instruction *br = factory.create<jit_cond_branch> (check, body,
604  entry_blocks[i + 1]);
605  block->append (br);
606  block = body;
607  }
608 
609  tree_statement_list *stmt_lst = tic->commands ();
610  assert (stmt_lst); // jwe: Can this be null?
611 
612  try
613  {
614  stmt_lst->accept (*this);
615  ++num_incomming;
616  block->append (factory.create<jit_branch> (tail));
617  }
618  catch (const jit_break_exception&)
619  { }
620 
621  current_breaks.splice (current_breaks.end (), breaks);
622  current_continues.splice (current_continues.end (), continues);
623  }
624 
625  breaks.splice (breaks.end (), current_breaks);
626  continues.splice (continues.end (), current_continues);
627 
628  if (num_incomming || ! last_else)
629  {
630  blocks.push_back (tail);
631  block = tail;
632  }
633  else
634  // every branch broke, so we don't have a tail
635  throw jit_break_exception ();
636 }
637 
638 void
640 {
641  result = resolve (exp);
642 }
643 
644 void
646 {
647  throw jit_fail_exception ("No visit_matrix implementation");
648 }
649 
650 void
652 {
653  throw jit_fail_exception ("No visit_cell implementation");
654 }
655 
656 void
658 {
659  throw jit_fail_exception ("No visit_multi_assignment implementation");
660 }
661 
662 void
664 {
665  throw jit_fail_exception ("No visit_no_op_command implementation");
666 }
667 
668 void
670 {
671  octave_value v = tc.rvalue1 ();
673 
674  if (ty == jit_typeinfo::get_scalar ())
675  {
676  double dv = v.double_value ();
678  }
679  else if (ty == jit_typeinfo::get_range ())
680  {
681  Range rv = v.range_value ();
683  }
684  else if (ty == jit_typeinfo::get_complex ())
685  {
686  Complex cv = v.complex_value ();
688  }
689  else
690  throw jit_fail_exception ("Unknown constant");
691 }
692 
693 void
695 {
696  throw jit_fail_exception ("No visit_fcn_handle implementation");
697 }
698 
699 void
701 {
702  throw jit_fail_exception ();
703 }
704 
705 void
707 {
708  throw jit_fail_exception ("No visit_parameter_list implementation");
709 }
710 
711 void
713 {
714  octave_value::unary_op etype = tpe.op_type ();
715  tree_expression *operand = tpe.operand ();
716  jit_value *operandv = visit (operand);
717 
718  const jit_operation& fn = jit_typeinfo::unary_op (etype);
719  result = create_checked (fn, operandv);
720 
721  if (etype == octave_value::op_incr || etype == octave_value::op_decr)
722  {
723  jit_value *ret = create_checked (&jit_typeinfo::grab, operandv);
724  do_assign (operand, result);
725  result = ret;
726  }
727 }
728 
729 void
731 {
732  octave_value::unary_op etype = tpe.op_type ();
733  tree_expression *operand = tpe.operand ();
734  const jit_operation& fn = jit_typeinfo::unary_op (etype);
735  result = create_checked (fn, visit (operand));
736 
737  if (etype == octave_value::op_incr || etype == octave_value::op_decr)
738  do_assign (operand, result);
739 }
740 
741 void
743 {
744  throw jit_fail_exception ("No visit_return_command implementation");
745 }
746 
747 void
749 {
750  throw jit_fail_exception ("No visit_return_list implementation");
751 }
752 
753 void
755 {
756  tree_expression *rhs = tsa.right_hand_side ();
757  jit_value *rhsv = visit (rhs);
758  octave_value::assign_op op = tsa.op_type ();
759 
760  if (op != octave_value::op_asn_eq)
761  {
762  // Do the equivalent binary operation, then assign.
763  // This is always correct, but it isn't always optimal.
764  tree_expression *lhs = tsa.left_hand_side ();
765  jit_value *lhsv = visit (lhs);
767  const jit_operation& fn = jit_typeinfo::binary_op (bop);
768  rhsv = create_checked (fn, lhsv, rhsv);
769  }
770 
771  result = do_assign (tsa.left_hand_side (), rhsv);
772 }
773 
774 void
776 {
777  tree_command *cmd = stmt.command ();
778  tree_expression *expr = stmt.expression ();
779 
780  if (cmd)
781  visit (cmd);
782  else
783  {
784  // stolen from octave::tree_evaluator::visit_statement
785  bool do_bind_ans = false;
786 
787  if (expr->is_identifier ())
788  {
789  tree_identifier *id = dynamic_cast<tree_identifier *> (expr);
790 
791  do_bind_ans = (! id->is_variable ());
792  }
793  else
794  do_bind_ans = (! expr->is_assignment_expression ());
795 
796  jit_value *expr_result = visit (expr);
797 
798  if (do_bind_ans)
799  do_assign ("ans", expr_result, expr->print_result ());
800  else if (expr->is_identifier () && expr->print_result ())
801  {
802  // FIXME: ugly hack, we need to come up with a way to pass
803  // nargout to visit_identifier
806  (expr->name ());
807  block->append (factory.create<jit_call> (fn, name, expr_result));
808  }
809  }
810 }
811 
812 void
814 {
815  for (tree_statement_list::iterator iter = lst.begin (); iter != lst.end();
816  ++iter)
817  {
818  tree_statement *elt = *iter;
819  // jwe: Can this ever be null?
820  assert (elt);
821  elt->accept (*this);
822  }
823 }
824 
825 void
827 {
828  throw jit_fail_exception ("No visit_switch_case implementation");
829 }
830 
831 void
833 {
834  throw jit_fail_exception ("No visit_switch_case_list implementation");
835 }
836 
837 void
839 {
840  tree_switch_case_list *lst = cmd.case_list ();
841 
842  // always visit switch expression
843  tree_expression *expr = cmd.switch_value ();
844  assert (expr && "Switch value can not be null");
845  jit_value *value = visit (expr);
846  assert (value);
847 
848  size_t case_blocks_num = lst->size ();
849 
850  if (! case_blocks_num) // there's nothing to do
851  return;
852 
853  // check for otherwise, it's interpreted as last 'else' condition
854  size_t has_otherwise = 0;
855  tree_switch_case *last = lst->back ();
856  if (last->is_default_case ())
857  has_otherwise = 1;
858 
859  std::vector<jit_block *> entry_blocks (case_blocks_num + 1 - has_otherwise);
860 
861  // the first entry point is always the actual block. Afterward, new blocks
862  // are created for every case and the otherwise branch
863  entry_blocks[0] = block;
864  for (size_t i = 1; i < case_blocks_num; ++i)
865  entry_blocks[i] = factory.create<jit_block> ("case_cond");
866 
867  jit_block *tail = factory.create<jit_block> ("switch_tail");
868 
869  // if there's no otherwise branch, the 'else' of the last branch
870  // has to point to the tail
871  if (! has_otherwise)
872  entry_blocks[entry_blocks.size()-1] = tail;
873 
874  // each branch in the case statement will have different breaks/continues
875  block_list current_breaks = breaks;
876  block_list current_continues = continues;
877  breaks.clear ();
878  continues.clear ();
879 
880  size_t num_incomming = 0; // number of incomming blocks to our tail
881 
882  tree_switch_case_list::iterator iter = lst->begin ();
883  for (size_t i = 0; i < case_blocks_num; ++iter, ++i)
884  {
885  tree_switch_case *twc = *iter;
886  block = entry_blocks[i]; // case_cond
887  assert (block);
888 
889  if (i)
890  blocks.push_back (entry_blocks[i]); // first block already pushed
891 
892  if (! twc->is_default_case ())
893  {
894  // compare result of switch expression with actual case label
895  tree_expression *te = twc->case_label ();
896  jit_value *label = visit (te);
897  assert(label);
898 
900  jit_value *cond = create_checked (fn, value, label);
901  assert(cond);
902 
904  cond);
905 
906  jit_block *body = factory.create<jit_block> ("case_body");
907  blocks.push_back (body);
908 
909  block->append (factory.create<jit_cond_branch> (check, body,
910  entry_blocks[i+1]));
911  block = body; // case_body
912  }
913 
914  tree_statement_list *stmt_lst = twc->commands ();
915  assert(stmt_lst);
916 
917  try
918  {
919  stmt_lst->accept (*this);
920  num_incomming++;
921  block->append (factory.create<jit_branch> (tail));
922  }
923  catch (const jit_break_exception&)
924  { }
925 
926  // each branch in the case statement will have different breaks/continues
927  current_breaks.splice (current_breaks.end (), breaks);
928  current_continues.splice (current_continues.end (), continues);
929  }
930 
931  // each branch in the case statement will have different breaks/continues
932  breaks.splice (breaks.end (), current_breaks);
933  continues.splice (continues.end (), current_continues);
934 
935  if (num_incomming || ! has_otherwise)
936  {
937  blocks.push_back (tail);
938  block = tail; // switch_tail
939  }
940  else
941  throw jit_break_exception (); // every branch broke
942 }
943 
944 void
946 {
947  throw jit_fail_exception ("No visit_try_catch_command implementation");
948 }
949 
950 void
952 {
953  throw jit_fail_exception ("No visit_unwind_protect_command implementation");
954 }
955 
956 void
958 {
960  frame.protect_var (breaks);
961  frame.protect_var (continues);
962  breaks.clear ();
963  continues.clear ();
964 
965  jit_block *cond_check = factory.create<jit_block> ("while_cond_check");
966  block->append (factory.create<jit_branch> (cond_check));
967  blocks.push_back (cond_check);
968  block = cond_check;
969 
970  tree_expression *expr = wc.condition ();
971  assert (expr && "While expression can not be null");
972  jit_value *check = visit (expr);
974 
975  jit_block *body = factory.create<jit_block> ("while_body");
976  blocks.push_back (body);
977 
978  jit_block *tail = factory.create<jit_block> ("while_tail");
979  block->append (factory.create<jit_cond_branch> (check, body, tail));
980  block = body;
981 
982  tree_statement_list *loop_body = wc.body ();
983  bool all_breaking = false;
984  if (loop_body)
985  {
986  try
987  {
988  loop_body->accept (*this);
989  }
990  catch (const jit_break_exception&)
991  {
992  all_breaking = true;
993  }
994  }
995 
996  finish_breaks (tail, breaks);
997 
998  if (! all_breaking || continues.size ())
999  {
1000  jit_block *interrupt_check
1001  = factory.create<jit_block> ("interrupt_check");
1002  blocks.push_back (interrupt_check);
1003  finish_breaks (interrupt_check, continues);
1004  if (! all_breaking)
1005  block->append (factory.create<jit_branch> (interrupt_check));
1006 
1007  block = interrupt_check;
1008  jit_error_check *ec
1010  cond_check, final_block);
1011  block->append (ec);
1012  }
1013 
1014  blocks.push_back (tail);
1015  block = tail;
1016 }
1017 
1018 void
1020 {
1022  frame.protect_var (breaks);
1023  frame.protect_var (continues);
1024  breaks.clear ();
1025  continues.clear ();
1026 
1027  jit_block *body = factory.create<jit_block> ("do_until_body");
1028  jit_block *cond_check = factory.create<jit_block> ("do_until_cond_check");
1029  jit_block *tail = factory.create<jit_block> ("do_until_tail");
1030 
1031  block->append (factory.create<jit_branch> (body));
1032  blocks.push_back (body);
1033  block = body;
1034 
1035  tree_statement_list *loop_body = duc.body ();
1036  bool all_breaking = false;
1037  if (loop_body)
1038  {
1039  try
1040  {
1041  loop_body->accept (*this);
1042  }
1043  catch (const jit_break_exception&)
1044  {
1045  all_breaking = true;
1046  }
1047  }
1048 
1049  finish_breaks (tail, breaks);
1050 
1051  if (! all_breaking || continues.size ())
1052  {
1053  jit_block *interrupt_check
1054  = factory.create<jit_block> ("interrupt_check");
1055  blocks.push_back (interrupt_check);
1056  finish_breaks (interrupt_check, continues);
1057  if (! all_breaking)
1058  block->append (factory.create<jit_branch> (interrupt_check));
1059 
1060  block = interrupt_check;
1061  jit_error_check *ec
1063  cond_check, final_block);
1064  block->append (ec);
1065 
1066  blocks.push_back (cond_check);
1067  block = cond_check;
1068 
1069  tree_expression *expr = duc.condition ();
1070  assert (expr && "Do-Until expression can not be null");
1071  jit_value *check = visit (expr);
1072  check = create_checked (&jit_typeinfo::logically_true, check);
1073 
1074  block->append (factory.create<jit_cond_branch> (check, tail, body));
1075  }
1076 
1077  blocks.push_back (tail);
1078  block = tail;
1079 }
1080 
1081 void
1083 {
1084  scope = s;
1085  iterator_count = 0;
1086  for_bounds_count = 0;
1087  short_count = 0;
1089 
1090  entry_block = factory.create<jit_block> ("body");
1091  final_block = factory.create<jit_block> ("final");
1093  entry_block->mark_alive ();
1094  block = entry_block;
1095 }
1096 
1097 jit_call *
1099 {
1100  block->append (ret);
1101 
1102  jit_block *normal = factory.create<jit_block> (block->name ());
1103  jit_error_check *check
1105  normal, final_block);
1106  block->append (check);
1107  blocks.push_back (normal);
1108  block = normal;
1109 
1110  return ret;
1111 }
1112 
1113 jit_variable *
1115 {
1116  variable_map::const_iterator iter;
1117  iter = vmap.find (vname);
1118  return iter != vmap.end () ? iter->second : 0;
1119 }
1120 
1121 jit_variable *
1123 {
1124  jit_variable *ret = find_variable (vname);
1125  if (ret)
1126  return ret;
1127 
1129  if (record.is_persistent () || record.is_global ())
1130  throw jit_fail_exception ("Persistent and global not yet supported");
1131 
1132  if (converting_function)
1133  return create_variable (vname, jit_typeinfo::get_any (), false);
1134  else
1135  {
1136  octave_value val = record.varval ();
1137  if (val.is_undefined ())
1138  val = symbol_table::find_function (vname);
1139 
1141  bounds.push_back (type_bound (type, vname));
1142 
1143  return create_variable (vname, type);
1144  }
1145 }
1146 
1147 jit_variable *
1149  bool isarg)
1150 {
1152 
1153  if (isarg)
1154  {
1155  jit_extract_argument *extract;
1156  extract = factory.create<jit_extract_argument> (type, var);
1157  entry_block->prepend (extract);
1158  }
1159  else
1160  {
1162  jit_assign *assign = factory.create<jit_assign> (var, init);
1163  entry_block->prepend (assign);
1164  entry_block->prepend (init);
1165  }
1166 
1167  return vmap[vname] = var;
1168 }
1169 
1171 jit_convert::next_name (const char *prefix, size_t& count, bool inc)
1172 {
1173  std::stringstream ss;
1174  ss << prefix << count;
1175  if (inc)
1176  ++count;
1177  return ss.str ();
1178 }
1179 
1182  bool lhs)
1183 {
1184  std::string type = exp.type_tags ();
1185  if (! (type.size () == 1 && type[0] == '('))
1186  throw jit_fail_exception ("Unsupported index operation");
1187 
1188  std::list<tree_argument_list *> args = exp.arg_lists ();
1189  if (args.size () != 1)
1190  throw jit_fail_exception ("Bad number of arguments in "
1191  "tree_index_expression");
1192 
1193  tree_argument_list *arg_list = args.front ();
1194  if (! arg_list)
1195  throw jit_fail_exception ("null argument list");
1196 
1197  if (arg_list->size () < 1)
1198  throw jit_fail_exception ("Empty arg_list");
1199 
1200  tree_expression *tree_object = exp.expression ();
1201  jit_value *object;
1202  if (lhs)
1203  {
1204  tree_identifier *id = dynamic_cast<tree_identifier *> (tree_object);
1205  if (! id)
1206  throw jit_fail_exception ("expected identifier");
1207  object = get_variable (id->name ());
1208  }
1209  else
1210  object = visit (tree_object);
1211 
1212  size_t narg = arg_list->size ();
1213  tree_argument_list::iterator iter = arg_list->begin ();
1214  bool have_extra = extra_arg;
1215  std::vector<jit_value *> call_args (narg + 1 + have_extra);
1216  call_args[0] = object;
1217 
1218  for (size_t idx = 0; iter != arg_list->end (); ++idx, ++iter)
1219  {
1221  frame.add_method (&end_context,
1222  &std::vector<jit_magic_end::context>::pop_back);
1223 
1224  jit_magic_end::context ctx (factory, object, idx, narg);
1225  end_context.push_back (ctx);
1226  call_args[idx + 1] = visit (*iter);
1227  }
1228 
1229  if (extra_arg)
1230  call_args[call_args.size () - 1] = extra_arg;
1231 
1232  const jit_operation& fres = lhs ? jit_typeinfo::paren_subsasgn ()
1234 
1235  return create_checked (fres, call_args);
1236 }
1237 
1238 jit_value *
1239 jit_convert::do_assign (tree_expression *exp, jit_value *rhs, bool artificial)
1240 {
1241  if (! exp)
1242  throw jit_fail_exception ("NULL lhs in assign");
1243 
1244  if (isa<tree_identifier> (exp))
1245  return do_assign (exp->name (), rhs, exp->print_result (), artificial);
1246  else if (tree_index_expression *idx
1247  = dynamic_cast<tree_index_expression *> (exp))
1248  {
1249  jit_value *new_object = resolve (*idx, rhs, true);
1250  do_assign (idx->expression (), new_object, true);
1251 
1252  // FIXME: Will not work for values that must be release/grabed
1253  return rhs;
1254  }
1255  else
1256  throw jit_fail_exception ("Unsupported assignment");
1257 }
1258 
1259 jit_value *
1261  bool print, bool artificial)
1262 {
1263  jit_variable *var = get_variable (lhs);
1264  jit_assign *assign = block->append (factory.create<jit_assign> (var, rhs));
1265 
1266  if (artificial)
1267  assign->mark_artificial ();
1268 
1269  if (print)
1270  {
1271  const jit_operation& print_fn = jit_typeinfo::print_value ();
1273  block->append (factory.create<jit_call> (print_fn, name, var));
1274  }
1275 
1276  return var;
1277 }
1278 
1279 jit_value *
1281 {
1283  frame.protect_var (result);
1284 
1285  tee.accept (*this);
1286  return result;
1287 }
1288 
1289 void
1291 {
1292  for (block_list::const_iterator iter = lst.begin (); iter != lst.end ();
1293  ++iter)
1294  {
1295  jit_block *b = *iter;
1296  b->append (factory.create<jit_branch> (dest));
1297  }
1298 }
1299 
1300 // -------------------- jit_convert_llvm --------------------
1301 llvm::Function *
1302 jit_convert_llvm::convert_loop (llvm::Module *module,
1303  const jit_block_list& blocks,
1304  const std::list<jit_value *>& constants)
1305 {
1306  converting_function = false;
1307 
1308  // for now just init arguments from entry, later we will have to do something
1309  // more interesting
1310  jit_block *entry_block = blocks.front ();
1311  for (jit_block::iterator iter = entry_block->begin ();
1312  iter != entry_block->end (); ++iter)
1313  if (jit_extract_argument *extract
1314  = dynamic_cast<jit_extract_argument *> (*iter))
1315  argument_vec.push_back (std::make_pair (extract->name (), true));
1316 
1318 
1319  // argument is an array of octave_base_value*, or octave_base_value**
1320  llvm::Type *arg_type = any->to_llvm (); // this is octave_base_value*
1321  arg_type = arg_type->getPointerTo ();
1322  llvm::FunctionType *ft;
1323  ft = llvm::FunctionType::get (llvm::Type::getVoidTy (context), arg_type,
1324  false);
1325  function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
1326  "foobar", module);
1327 
1328  try
1329  {
1330  prelude = llvm::BasicBlock::Create (context, "prelude", function);
1331  builder.SetInsertPoint (prelude);
1332 
1333  llvm::Value *arg = function->arg_begin ();
1334  for (size_t i = 0; i < argument_vec.size (); ++i)
1335  {
1336  llvm::Value *loaded_arg = builder.CreateConstInBoundsGEP1_32 (arg, i);
1337  arguments[argument_vec[i].first] = loaded_arg;
1338  }
1339 
1340  convert (blocks, constants);
1341  }
1342  catch (const jit_fail_exception& e)
1343  {
1344  function->eraseFromParent ();
1345  throw;
1346  }
1347 
1348  return function;
1349 }
1350 
1353  const jit_block_list& blocks,
1354  const std::list<jit_value *>& constants,
1356  const std::vector<jit_type *>& args)
1357 {
1358  converting_function = true;
1359 
1360  jit_block *final_block = blocks.back ();
1361  jit_return *ret = dynamic_cast<jit_return *> (final_block->back ());
1362  assert (ret);
1363 
1365  "foobar", ret->result_type (), args);
1366  function = creating.to_llvm ();
1367 
1368  try
1369  {
1370  prelude = creating.new_block ("prelude");
1371  builder.SetInsertPoint (prelude);
1372 
1373  tree_parameter_list *plist = fcn.parameter_list ();
1374  if (plist)
1375  {
1376  tree_parameter_list::iterator piter = plist->begin ();
1377  tree_parameter_list::iterator pend = plist->end ();
1378  for (size_t i = 0; i < args.size () && piter != pend; ++i, ++piter)
1379  {
1380  tree_decl_elt *elt = *piter;
1381  std::string arg_name = elt->name ();
1382  arguments[arg_name] = creating.argument (builder, i);
1383  }
1384  }
1385 
1386  convert (blocks, constants);
1387  }
1388  catch (const jit_fail_exception& e)
1389  {
1390  function->eraseFromParent ();
1391  throw;
1392  }
1393 
1394  return creating;
1395 }
1396 
1397 void
1399  const std::list<jit_value *>& constants)
1400 {
1401  std::list<jit_block *>::const_iterator biter;
1402  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1403  {
1404  jit_block *jblock = *biter;
1405  llvm::BasicBlock *block = llvm::BasicBlock::Create (context,
1406  jblock->name (),
1407  function);
1408  jblock->stash_llvm (block);
1409  }
1410 
1411  jit_block *first = *blocks.begin ();
1412  builder.CreateBr (first->to_llvm ());
1413 
1414  // constants aren't in the IR, we visit those first
1415  for (std::list<jit_value *>::const_iterator iter = constants.begin ();
1416  iter != constants.end (); ++iter)
1417  if (! isa<jit_instruction> (*iter))
1418  visit (*iter);
1419 
1420  // convert all instructions
1421  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1422  visit (*biter);
1423 
1424  // now finish phi nodes
1425  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1426  {
1427  jit_block& block = **biter;
1428  for (jit_block::iterator piter = block.begin ();
1429  piter != block.end () && isa<jit_phi> (*piter); ++piter)
1430  {
1431  jit_instruction *phi = *piter;
1432  finish_phi (static_cast<jit_phi *> (phi));
1433  }
1434  }
1435 }
1436 
1437 void
1439 {
1440  llvm::PHINode *llvm_phi = phi->to_llvm ();
1441  for (size_t i = 0; i < phi->argument_count (); ++i)
1442  {
1443  llvm::BasicBlock *pred = phi->incomming_llvm (i);
1444  llvm_phi->addIncoming (phi->argument_llvm (i), pred);
1445  }
1446 }
1447 
1448 void
1450 {
1451  cs.stash_llvm (builder.CreateGlobalStringPtr (cs.value ()));
1452 }
1453 
1454 void
1456 {
1457  cb.stash_llvm (llvm::ConstantInt::get (cb.type_llvm (), cb.value ()));
1458 }
1459 
1460 void
1462 {
1463  cs.stash_llvm (llvm::ConstantFP::get (cs.type_llvm (), cs.value ()));
1464 }
1465 
1466 void
1468 {
1469  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
1470  Complex value = cc.value ();
1471  llvm::Value *real = llvm::ConstantFP::get (scalar_t, value.real ());
1472  llvm::Value *imag = llvm::ConstantFP::get (scalar_t, value.imag ());
1473  cc.stash_llvm (jit_typeinfo::create_complex (real, imag));
1474 }
1475 
1477 {
1478  ci.stash_llvm (llvm::ConstantInt::get (ci.type_llvm (), ci.value ()));
1479 }
1480 
1481 void
1483 {
1484  llvm::StructType *stype = llvm::cast<llvm::StructType>(cr.type_llvm ());
1485  llvm::Type *scalar_t = jit_typeinfo::get_scalar_llvm ();
1486  llvm::Type *idx = jit_typeinfo::get_index_llvm ();
1487  const jit_range& rng = cr.value ();
1488 
1489  llvm::Constant *constants[4];
1490  constants[0] = llvm::ConstantFP::get (scalar_t, rng.base);
1491  constants[1] = llvm::ConstantFP::get (scalar_t, rng.limit);
1492  constants[2] = llvm::ConstantFP::get (scalar_t, rng.inc);
1493  constants[3] = llvm::ConstantInt::get (idx, rng.nelem);
1494 
1495  llvm::Value *as_llvm;
1496  as_llvm = llvm::ConstantStruct::get (stype,
1497  llvm::makeArrayRef (constants, 4));
1498  cr.stash_llvm (as_llvm);
1499 }
1500 
1501 void
1503 {
1504  llvm::BasicBlock *block = b.to_llvm ();
1505  builder.SetInsertPoint (block);
1506  for (jit_block::iterator iter = b.begin (); iter != b.end (); ++iter)
1507  visit (*iter);
1508 }
1509 
1510 void
1512 {
1513  b.stash_llvm (builder.CreateBr (b.successor_llvm ()));
1514 }
1515 
1516 void
1518 {
1519  llvm::Value *cond = cb.cond_llvm ();
1520  llvm::Value *br;
1521  br = builder.CreateCondBr (cond, cb.successor_llvm (0),
1522  cb.successor_llvm (1));
1523  cb.stash_llvm (br);
1524 }
1525 
1526 void
1528 {
1529  const jit_function& ol = call.overload ();
1530 
1531  std::vector<jit_value *> args (call.arguments ().size ());
1532  for (size_t i = 0; i < args.size (); ++i)
1533  args[i] = call.argument (i);
1534 
1535  llvm::Value *ret = ol.call (builder, args);
1536  call.stash_llvm (ret);
1537 }
1538 
1539 void
1541 {
1542  llvm::Value *arg = arguments[extract.name ()];
1543  assert (arg);
1544 
1545  if (converting_function)
1546  extract.stash_llvm (arg);
1547  else
1548  {
1549  arg = builder.CreateLoad (arg);
1550 
1551  const jit_function& ol = extract.overload ();
1552  extract.stash_llvm (ol.call (builder, arg));
1553  }
1554 }
1555 
1556 void
1558 {
1559  const jit_function& ol = store.overload ();
1560  llvm::Value *arg_value = ol.call (builder, store.result ());
1561  llvm::Value *arg = arguments[store.name ()];
1562  store.stash_llvm (builder.CreateStore (arg_value, arg));
1563 }
1564 
1565 void
1567 {
1568  jit_value *res = ret.result ();
1569 
1570  if (converting_function)
1571  creating.do_return (builder, res->to_llvm (), false);
1572  else
1573  {
1574  if (res)
1575  builder.CreateRet (res->to_llvm ());
1576  else
1577  builder.CreateRetVoid ();
1578  }
1579 }
1580 
1581 void
1583 {
1584  // we might not have converted all incoming branches, so we don't
1585  // set incomming branches now
1586  llvm::PHINode *node = llvm::PHINode::Create (phi.type_llvm (),
1587  phi.argument_count ());
1588  builder.Insert (node);
1589  phi.stash_llvm (node);
1590 }
1591 
1592 void
1594 {
1595  throw jit_fail_exception ("ERROR: SSA construction should remove all variables");
1596 }
1597 
1598 void
1600 {
1601  llvm::Value *cond;
1602 
1603  switch (check.check_variable ())
1604  {
1607  break;
1610  break;
1611  default:
1612  panic_impossible ();
1613  }
1614 
1615  llvm::Value *br = builder.CreateCondBr (cond, check.successor_llvm (0),
1616  check.successor_llvm (1));
1617  check.stash_llvm (br);
1618 }
1619 
1620 void
1622 {
1623  jit_value *new_value = assign.src ();
1624  assign.stash_llvm (new_value->to_llvm ());
1625 
1626  if (assign.artificial ())
1627  return;
1628 
1629  jit_value *overwrite = assign.overwrite ();
1630  if (isa<jit_assign_base> (overwrite))
1631  {
1632  const jit_function& ol = jit_typeinfo::get_release (overwrite->type ());
1633  if (ol.valid ())
1634  ol.call (builder, overwrite);
1635  }
1636 }
1637 
1638 void
1640 { }
1641 
1642 void
1644 {
1645  const jit_function& ol = me.overload ();
1646 
1648  llvm::Value *ret = ol.call (builder, ctx.value, ctx.index, ctx.count);
1649  me.stash_llvm (ret);
1650 }
1651 
1652 // -------------------- jit_infer --------------------
1654  const variable_map& avmap)
1655  : blocks (ablocks), factory (afactory), vmap (avmap) { }
1656 
1657 void
1659 {
1660  construct_ssa ();
1661 
1662  // initialize the worklist to instructions derived from constants
1663  const std::list<jit_value *>& constants = factory.constants ();
1664  for (std::list<jit_value *>::const_iterator iter = constants.begin ();
1665  iter != constants.end (); ++iter)
1666  append_users (*iter);
1667 
1668  // the entry block terminator may be a regular branch statement
1669  if (entry_block ().terminator ())
1671 
1672  // FIXME: Describe algorithm here
1673  while (worklist.size ())
1674  {
1675  jit_instruction *next = worklist.front ();
1676  worklist.pop_front ();
1677  next->stash_in_worklist (false);
1678 
1679  if (next->infer ())
1680  {
1681  // terminators need to be handles specially
1682  if (jit_terminator *term = dynamic_cast<jit_terminator *> (next))
1683  append_users_term (term);
1684  else
1685  append_users (next);
1686  }
1687  }
1688 
1689  remove_dead ();
1690  blocks.label ();
1691  place_releases ();
1692  simplify_phi ();
1693 }
1694 
1695 void
1697 {
1698  for (jit_use *use = v->first_use (); use; use = use->next ())
1699  push_worklist (use->user ());
1700 }
1701 
1702 void
1704 {
1705  for (size_t i = 0; i < term->successor_count (); ++i)
1706  {
1707  if (term->alive (i))
1708  {
1709  jit_block *succ = term->successor (i);
1710  for (jit_block::iterator iter = succ->begin ();
1711  iter != succ->end () && isa<jit_phi> (*iter); ++iter)
1712  push_worklist (*iter);
1713 
1714  jit_terminator *sterm = succ->terminator ();
1715  if (sterm)
1716  push_worklist (sterm);
1717  }
1718  }
1719 }
1720 
1721 void
1723 {
1724  blocks.label ();
1726  entry_block ().compute_df ();
1728 
1729  // insert phi nodes where needed, this is done on a per variable basis
1730  for (variable_map::const_iterator iter = vmap.begin (); iter != vmap.end ();
1731  ++iter)
1732  {
1733  jit_block::df_set visited, added_phi;
1734  std::list<jit_block *> ssa_worklist;
1735  iter->second->use_blocks (visited);
1736  ssa_worklist.insert (ssa_worklist.begin (), visited.begin (),
1737  visited.end ());
1738 
1739  while (ssa_worklist.size ())
1740  {
1741  jit_block *b = ssa_worklist.front ();
1742  ssa_worklist.pop_front ();
1743 
1744  for (jit_block::df_iterator diter = b->df_begin ();
1745  diter != b->df_end (); ++diter)
1746  {
1747  jit_block *dblock = *diter;
1748  if (! added_phi.count (dblock))
1749  {
1750  jit_phi *phi = factory.create<jit_phi> (iter->second,
1751  dblock->use_count ());
1752  dblock->prepend (phi);
1753  added_phi.insert (dblock);
1754  }
1755 
1756  if (! visited.count (dblock))
1757  {
1758  ssa_worklist.push_back (dblock);
1759  visited.insert (dblock);
1760  }
1761  }
1762  }
1763  }
1764 
1765  do_construct_ssa (entry_block (), entry_block ().visit_count ());
1766 }
1767 
1768 void
1769 jit_infer::do_construct_ssa (jit_block& ablock, size_t avisit_count)
1770 {
1771  if (ablock.visited (avisit_count))
1772  return;
1773 
1774  // replace variables with their current SSA value
1775  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ();
1776  ++iter)
1777  {
1778  jit_instruction *instr = *iter;
1779  instr->construct_ssa ();
1780  instr->push_variable ();
1781  }
1782 
1783  // finish phi nodes of successors
1784  for (size_t i = 0; i < ablock.successor_count (); ++i)
1785  {
1786  jit_block *finish = ablock.successor (i);
1787 
1788  for (jit_block::iterator iter = finish->begin ();
1789  iter != finish->end () && isa<jit_phi> (*iter);)
1790  {
1791  jit_phi *phi = static_cast<jit_phi *> (*iter);
1792  jit_variable *var = phi->dest ();
1793  ++iter;
1794 
1795  if (var->has_top ())
1796  phi->add_incomming (&ablock, var->top ());
1797  else
1798  {
1799  // temporaries may have extranious phi nodes which can be removed
1800  assert (! phi->use_count ());
1801  assert (var->name ().size () && var->name ()[0] == '#');
1802  phi->remove ();
1803  }
1804  }
1805  }
1806 
1807  for (size_t i = 0; i < ablock.dom_successor_count (); ++i)
1808  do_construct_ssa (*ablock.dom_successor (i), avisit_count);
1809 
1810  ablock.pop_all ();
1811 }
1812 
1813 void
1815 {
1816  std::set<jit_value *> temporaries;
1817  for (jit_block_list::iterator iter = blocks.begin (); iter != blocks.end ();
1818  ++iter)
1819  {
1820  jit_block& ablock = **iter;
1821  if (ablock.id () != jit_block::NO_ID)
1822  {
1823  release_temp (ablock, temporaries);
1824  release_dead_phi (ablock);
1825  }
1826  }
1827 }
1828 
1829 void
1831 {
1832  if (! instr->in_worklist ())
1833  {
1834  instr->stash_in_worklist (true);
1835  worklist.push_back (instr);
1836  }
1837 }
1838 
1839 void
1841 {
1843  for (biter = blocks.begin (); biter != blocks.end (); ++biter)
1844  {
1845  jit_block *b = *biter;
1846  if (b->alive ())
1847  {
1848  for (jit_block::iterator iter = b->begin ();
1849  iter != b->end () && isa<jit_phi> (*iter);)
1850  {
1851  jit_phi *phi = static_cast<jit_phi *> (*iter);
1852  if (phi->prune ())
1853  iter = b->remove (iter);
1854  else
1855  ++iter;
1856  }
1857  }
1858  }
1859 
1860  for (biter = blocks.begin (); biter != blocks.end ();)
1861  {
1862  jit_block *b = *biter;
1863  if (b->alive ())
1864  {
1865  // FIXME: A special case for jit_error_check, if we generalize to
1866  // we will need to change!
1867  jit_terminator *term = b->terminator ();
1868  if (term && term->successor_count () == 2 && ! term->alive (0))
1869  {
1870  jit_block *succ = term->successor (1);
1871  term->remove ();
1872  jit_branch *abreak = factory.create<jit_branch> (succ);
1873  b->append (abreak);
1874  abreak->infer ();
1875  }
1876 
1877  ++biter;
1878  }
1879  else
1880  {
1881  jit_terminator *term = b->terminator ();
1882  if (term)
1883  term->remove ();
1884  biter = blocks.erase (biter);
1885  }
1886  }
1887 }
1888 
1889 void
1891 {
1892  jit_block::iterator iter = ablock.begin ();
1893  while (iter != ablock.end () && isa<jit_phi> (*iter))
1894  {
1895  jit_phi *phi = static_cast<jit_phi *> (*iter);
1896  ++iter;
1897 
1898  jit_use *use = phi->first_use ();
1899  if (phi->use_count () == 1 && isa<jit_assign> (use->user ()))
1900  {
1901  // instead of releasing on assign, release on all incomming branches,
1902  // this can get rid of casts inside loops
1903  for (size_t i = 0; i < phi->argument_count (); ++i)
1904  {
1905  jit_value *arg = phi->argument (i);
1906  if (! arg->needs_release ())
1907  continue;
1908 
1909  jit_block *inc = phi->incomming (i);
1910  jit_block *split = inc->maybe_split (factory, blocks, ablock);
1911  jit_terminator *term = split->terminator ();
1912  jit_call *release
1914  release->infer ();
1915  split->insert_before (term, release);
1916  }
1917 
1918  phi->replace_with (0);
1919  phi->remove ();
1920  }
1921  }
1922 }
1923 
1924 void
1925 jit_infer::release_temp (jit_block& ablock, std::set<jit_value *>& temp)
1926 {
1927  for (jit_block::iterator iter = ablock.begin (); iter != ablock.end ();
1928  ++iter)
1929  {
1930  jit_instruction *instr = *iter;
1931 
1932  // check for temporaries that require release and live across
1933  // multiple blocks
1934  if (instr->needs_release ())
1935  {
1936  jit_block *fu_block = instr->first_use_block ();
1937  if (fu_block && fu_block != &ablock && instr->needs_release ())
1938  temp.insert (instr);
1939  }
1940 
1941  if (isa<jit_call> (instr))
1942  {
1943  // place releases for temporary arguments
1944  for (size_t i = 0; i < instr->argument_count (); ++i)
1945  {
1946  jit_value *arg = instr->argument (i);
1947  if (! arg->needs_release ())
1948  continue;
1949 
1950  jit_call *release
1952  release->infer ();
1953  ablock.insert_after (iter, release);
1954  ++iter;
1955  temp.erase (arg);
1956  }
1957  }
1958  }
1959 
1960  if (! temp.size () || ! isa<jit_error_check> (ablock.terminator ()))
1961  return;
1962 
1963  // FIXME: If we support try/catch or unwind_protect final_block
1964  // may not be the destination
1965  jit_block *split = ablock.maybe_split (factory, blocks, final_block ());
1966  jit_terminator *term = split->terminator ();
1967  for (std::set<jit_value *>::const_iterator iter = temp.begin ();
1968  iter != temp.end (); ++iter)
1969  {
1970  jit_value *value = *iter;
1971  jit_call *release
1973  split->insert_before (term, release);
1974  release->infer ();
1975  }
1976 }
1977 
1978 void
1980 {
1981  for (jit_block_list::iterator biter = blocks.begin (); biter != blocks.end ();
1982  ++biter)
1983  {
1984  jit_block &ablock = **biter;
1985  for (jit_block::iterator iter = ablock.begin ();
1986  iter != ablock.end () && isa<jit_phi> (*iter); ++iter)
1987  simplify_phi (*static_cast<jit_phi *> (*iter));
1988  }
1989 }
1990 
1991 void
1993 {
1994  jit_block& pblock = *phi.parent ();
1995  const jit_operation& cast_fn = jit_typeinfo::cast (phi.type ());
1996  jit_variable *dest = phi.dest ();
1997  for (size_t i = 0; i < phi.argument_count (); ++i)
1998  {
1999  jit_value *arg = phi.argument (i);
2000  if (arg->type () != phi.type ())
2001  {
2002  jit_block *pred = phi.incomming (i);
2003  jit_block *split = pred->maybe_split (factory, blocks, pblock);
2004  jit_terminator *term = split->terminator ();
2005  jit_instruction *cast = factory.create<jit_call> (cast_fn, arg);
2006  jit_assign *assign = factory.create<jit_assign> (dest, cast);
2007 
2008  split->insert_before (term, cast);
2009  split->insert_before (term, assign);
2010  cast->infer ();
2011  assign->infer ();
2012  phi.stash_argument (i, assign);
2013  }
2014  }
2015 }
2016 
2017 // -------------------- tree_jit --------------------
2018 
2019 tree_jit::tree_jit (void) : module (0), engine (0)
2020 { }
2021 
2023 { }
2024 
2025 bool
2027 {
2028  return instance ().do_execute (cmd, bounds);
2029 }
2030 
2031 bool
2033 {
2034  return instance ().do_execute (cmd);
2035 }
2036 
2037 bool
2040 {
2041  return instance ().do_execute (fcn, args, retval);
2042 }
2043 
2044 tree_jit&
2046 {
2047  static tree_jit ret;
2048  return ret;
2049 }
2050 
2051 bool
2053 {
2054  if (engine)
2055  return true;
2056 
2057  if (! module)
2058  {
2059  llvm::InitializeNativeTarget ();
2060  module = new llvm::Module ("octave", context);
2061  }
2062 
2063  // sometimes this fails pre main
2064  engine = llvm::ExecutionEngine::createJIT (module);
2065 
2066  if (! engine)
2067  return false;
2068 
2069 #if defined (LEGACY_PASSMANAGER)
2070  module_pass_manager = new llvm::legacy::PassManager ();
2071  pass_manager = new llvm::legacy::FunctionPassManager (module);
2072 #else
2073  module_pass_manager = new llvm::PassManager ();
2074  pass_manager = new llvm::FunctionPassManager (module);
2075 #endif
2076  module_pass_manager->add (llvm::createAlwaysInlinerPass ());
2077 
2078 #if defined (HAVE_LLVM_DATALAYOUT)
2079  pass_manager->add (new llvm::DataLayout (*engine->getDataLayout ()));
2080 #else
2081  pass_manager->add (new llvm::TargetData (*engine->getTargetData ()));
2082 #endif
2083  pass_manager->add (llvm::createCFGSimplificationPass ());
2084  pass_manager->add (llvm::createBasicAliasAnalysisPass ());
2085  pass_manager->add (llvm::createPromoteMemoryToRegisterPass ());
2086  pass_manager->add (llvm::createInstructionCombiningPass ());
2087  pass_manager->add (llvm::createReassociatePass ());
2088  pass_manager->add (llvm::createGVNPass ());
2089  pass_manager->add (llvm::createCFGSimplificationPass ());
2090  pass_manager->doInitialization ();
2091 
2093 
2094  return true;
2095 }
2096 
2097 bool
2099 {
2100  size_t tc = trip_count (bounds);
2101  if (! tc || ! initialize () || ! enabled ())
2102  return false;
2103 
2104  jit_info::vmap extra_vars;
2105  extra_vars["#for_bounds0"] = &bounds;
2106 
2107  jit_info *info = cmd.get_info ();
2108  if (! info || ! info->match (extra_vars))
2109  {
2110  if (tc < static_cast<size_t> (Vjit_startcnt))
2111  return false;
2112 
2113  delete info;
2114  info = new jit_info (*this, cmd, bounds);
2115  cmd.stash_info (info);
2116  }
2117 
2118  return info->execute (extra_vars);
2119 }
2120 
2121 bool
2123 {
2124  if (! initialize () || ! enabled ())
2125  return false;
2126 
2127  jit_info *info = cmd.get_info ();
2128  if (! info || ! info->match ())
2129  {
2130  delete info;
2131  info = new jit_info (*this, cmd);
2132  cmd.stash_info (info);
2133  }
2134 
2135  return info->execute ();
2136 }
2137 
2138 bool
2141 {
2142  if (! initialize () || ! enabled ())
2143  return false;
2144 
2145  jit_function_info *info = fcn.get_info ();
2146  if (! info || ! info->match (args))
2147  {
2148  delete info;
2149  info = new jit_function_info (*this, fcn, args);
2150  fcn.stash_info (info);
2151  }
2152 
2153  return info->execute (args, retval);
2154 }
2155 
2156 bool
2158 {
2159  // Ideally, we should only disable JIT if there is a breakpoint in the code
2160  // we are about to run. However, we can't figure this out in O(1) time, so
2161  // we conservatively check for the existence of any breakpoints.
2162  return (Vjit_enable && ! bp_table::have_breakpoints ()
2164 }
2165 
2166 size_t
2167 tree_jit::trip_count (const octave_value& bounds) const
2168 {
2169  if (bounds.is_range ())
2170  {
2171  Range rng = bounds.range_value ();
2172  return rng.numel ();
2173  }
2174 
2175  // unsupported type
2176  return 0;
2177 }
2178 
2179 void
2180 tree_jit::optimize (llvm::Function *fn)
2181 {
2182  if (Vdebug_jit)
2183  llvm::verifyModule (*module);
2184 
2185  module_pass_manager->run (*module);
2186  pass_manager->run (*fn);
2187 
2188  if (Vdebug_jit)
2189  {
2191 #if defined (RAW_FD_OSTREAM_ARG_IS_LLVM_SYS_FS)
2192  llvm::raw_fd_ostream fout ("test.bc", error,
2193  llvm::sys::fs::F_Binary);
2194 #else
2195  llvm::raw_fd_ostream fout ("test.bc", error,
2196  llvm::raw_fd_ostream::F_Binary);
2197 #endif
2198  llvm::WriteBitcodeToFile (module, fout);
2199  }
2200 }
2201 
2202 // -------------------- jit_function_info --------------------
2205  const octave_value_list& ov_args)
2206  : argument_types (ov_args.length ()), function (0)
2207 {
2208  size_t nargs = ov_args.length ();
2209  for (size_t i = 0; i < nargs; ++i)
2210  argument_types[i] = jit_typeinfo::type_of (ov_args(i));
2211 
2212  jit_function raw_fn;
2213  jit_function wrapper;
2214 
2215  try
2216  {
2217  jit_convert conv (fcn, argument_types);
2218  jit_infer infer (conv.get_factory (), conv.get_blocks (),
2219  conv.get_variable_map ());
2220  infer.infer ();
2221 
2222  if (Vdebug_jit)
2223  {
2224  jit_block_list& blocks = infer.get_blocks ();
2225  blocks.label ();
2226  std::cout << "-------------------- Compiling function ";
2227  std::cout << "--------------------\n";
2228 
2229  tree_print_code tpc (std::cout);
2231  tpc.visit_statement_list (*fcn.body ());
2233  blocks.print (std::cout, "octave jit ir");
2234  }
2235 
2236  jit_factory& factory = conv.get_factory ();
2237  llvm::Module *module = tjit.get_module ();
2238  jit_convert_llvm to_llvm;
2239  raw_fn = to_llvm.convert_function (module, infer.get_blocks (),
2240  factory.constants (), fcn,
2241  argument_types);
2242 
2243  if (Vdebug_jit)
2244  {
2245  std::cout << "-------------------- raw function ";
2246  std::cout << "--------------------\n";
2247  std::cout << *raw_fn.to_llvm () << std::endl;
2248  llvm::verifyFunction (*raw_fn.to_llvm ());
2249  }
2250 
2251  std::string wrapper_name = fcn.name () + "_wrapper";
2252  jit_type *any_t = jit_typeinfo::get_any ();
2253  std::vector<jit_type *> wrapper_args (1, jit_typeinfo::get_any_ptr ());
2254  wrapper = jit_function (module, jit_convention::internal, wrapper_name,
2255  any_t, wrapper_args);
2256 
2257  llvm::BasicBlock *wrapper_body = wrapper.new_block ();
2258  builder.SetInsertPoint (wrapper_body);
2259 
2260  llvm::Value *wrapper_arg = wrapper.argument (builder, 0);
2261  std::vector<llvm::Value *> raw_args (nargs);
2262  for (size_t i = 0; i < nargs; ++i)
2263  {
2264  llvm::Value *arg;
2265  arg = builder.CreateConstInBoundsGEP1_32 (wrapper_arg, i);
2266  arg = builder.CreateLoad (arg);
2267 
2268  jit_type *arg_type = argument_types[i];
2269  const jit_function& cast = jit_typeinfo::cast (arg_type, any_t);
2270  raw_args[i] = cast.call (builder, arg);
2271  }
2272 
2273  llvm::Value *result = raw_fn.call (builder, raw_args);
2274  if (raw_fn.result ())
2275  {
2276  jit_type *raw_result_t = raw_fn.result ();
2277  const jit_function& cast = jit_typeinfo::cast (any_t, raw_result_t);
2278  result = cast.call (builder, result);
2279  }
2280  else
2281  {
2282  llvm::Value *zero = builder.getInt32 (0);
2283  result = builder.CreateBitCast (zero, any_t->to_llvm ());
2284  }
2285 
2286  wrapper.do_return (builder, result);
2287 
2288  llvm::Function *llvm_function = wrapper.to_llvm ();
2289  tjit.optimize (llvm_function);
2290 
2291  if (Vdebug_jit)
2292  {
2293  std::cout << "-------------------- optimized and wrapped ";
2294  std::cout << "--------------------\n";
2295  std::cout << *llvm_function << std::endl;
2296  llvm::verifyFunction (*llvm_function);
2297  }
2298 
2299  llvm::ExecutionEngine* engine = tjit.get_engine ();
2300  void *void_fn = engine->getPointerToFunction (llvm_function);
2301  function = reinterpret_cast<jited_function> (void_fn);
2302  }
2303  catch (const jit_fail_exception& e)
2304  {
2305  argument_types.clear ();
2306 
2307  if (Vdebug_jit)
2308  {
2309  if (e.known ())
2310  std::cout << "jit fail: " << e.what () << std::endl;
2311  }
2312 
2313  Vjit_failcnt++;
2314 
2315  wrapper.erase ();
2316  raw_fn.erase ();
2317  }
2318 }
2319 
2320 bool
2322  octave_value_list& retval) const
2323 {
2324  if (! function)
2325  return false;
2326 
2327  // FIXME: figure out a way to delete ov_args so we avoid duplicating refcount
2328  size_t nargs = ov_args.length ();
2329  std::vector<octave_base_value *> args (nargs);
2330  for (size_t i = 0; i < nargs; ++i)
2331  {
2332  octave_base_value *obv = ov_args(i).internal_rep ();
2333  obv->grab ();
2334  args[i] = obv;
2335  }
2336 
2337  octave_base_value *ret = function (&args[0]);
2338  if (ret)
2339  retval(0) = octave_value (ret);
2340 
2341  octave_quit ();
2342 
2343  return true;
2344 }
2345 
2346 bool
2348 {
2349  if (! function)
2350  return true;
2351 
2352  size_t nargs = ov_args.length ();
2353  if (nargs != argument_types.size ())
2354  return false;
2355 
2356  for (size_t i = 0; i < nargs; ++i)
2357  if (jit_typeinfo::type_of (ov_args(i)) != argument_types[i])
2358  return false;
2359 
2360  return true;
2361 }
2362 
2363 // -------------------- jit_info --------------------
2365  : engine (tjit.get_engine ()), function (0), llvm_function (0)
2366 {
2367  compile (tjit, tee);
2368 }
2369 
2370 jit_info::jit_info (tree_jit& tjit, tree& tee, const octave_value& for_bounds)
2371  : engine (tjit.get_engine ()), function (0), llvm_function (0)
2372 {
2373  compile (tjit, tee, jit_typeinfo::type_of (for_bounds));
2374 }
2375 
2377 {
2378  if (llvm_function)
2379  llvm_function->eraseFromParent ();
2380 }
2381 
2382 bool
2383 jit_info::execute (const vmap& extra_vars) const
2384 {
2385  if (! function)
2386  return false;
2387 
2388  std::vector<octave_base_value *> real_arguments (arguments.size ());
2389  for (size_t i = 0; i < arguments.size (); ++i)
2390  {
2391  if (arguments[i].second)
2392  {
2393  octave_value current = find (extra_vars, arguments[i].first);
2394  octave_base_value *obv = current.internal_rep ();
2395  obv->grab ();
2396  real_arguments[i] = obv;
2397  }
2398  }
2399 
2400  function (&real_arguments[0]);
2401 
2402  for (size_t i = 0; i < arguments.size (); ++i)
2403  {
2404  const std::string& name = arguments[i].first;
2405 
2406  // do not store for loop bounds temporary
2407  if (name.size () && name[0] != '#')
2408  symbol_table::assign (arguments[i].first, real_arguments[i]);
2409  }
2410 
2411  octave_quit ();
2412 
2413  return true;
2414 }
2415 
2416 bool
2417 jit_info::match (const vmap& extra_vars) const
2418 {
2419  if (! function)
2420  return true;
2421 
2422  for (size_t i = 0; i < bounds.size (); ++i)
2423  {
2424  const std::string& arg_name = bounds[i].second;
2425  octave_value value = find (extra_vars, arg_name);
2426  jit_type *type = jit_typeinfo::type_of (value);
2427 
2428  // FIXME: Check for a parent relationship
2429  if (type != bounds[i].first)
2430  return false;
2431  }
2432 
2433  return true;
2434 }
2435 
2436 void
2437 jit_info::compile (tree_jit& tjit, tree& tee, jit_type *for_bounds)
2438 {
2439  try
2440  {
2441  jit_convert conv (tee, for_bounds);
2442  jit_infer infer (conv.get_factory (), conv.get_blocks (),
2443  conv.get_variable_map ());
2444 
2445  infer.infer ();
2446 
2447  if (Vdebug_jit)
2448  {
2449  jit_block_list& blocks = infer.get_blocks ();
2450  blocks.label ();
2451  std::cout << "-------------------- Compiling tree --------------------\n";
2452  std::cout << tee.str_print_code () << std::endl;
2453  blocks.print (std::cout, "octave jit ir");
2454  }
2455 
2456  jit_factory& factory = conv.get_factory ();
2457  jit_convert_llvm to_llvm;
2458  llvm_function = to_llvm.convert_loop (tjit.get_module (),
2459  infer.get_blocks (),
2460  factory.constants ());
2461  arguments = to_llvm.get_arguments ();
2462  bounds = conv.get_bounds ();
2463  }
2464  catch (const jit_fail_exception& e)
2465  {
2466  if (Vdebug_jit)
2467  {
2468  if (e.known ())
2469  std::cout << "jit fail: " << e.what () << std::endl;
2470  }
2471 
2472  Vjit_failcnt++;
2473 
2474  }
2475 
2476  if (llvm_function)
2477  {
2478  if (Vdebug_jit)
2479  {
2480  std::cout << "-------------------- llvm ir --------------------";
2481  std::cout << *llvm_function << std::endl;
2482  llvm::verifyFunction (*llvm_function);
2483  }
2484 
2485  tjit.optimize (llvm_function);
2486 
2487  if (Vdebug_jit)
2488  {
2489  std::cout << "-------------------- optimized llvm ir "
2490  << "--------------------\n";
2491  std::cout << *llvm_function << std::endl;
2492  }
2493 
2494  void *void_fn = engine->getPointerToFunction (llvm_function);
2495  function = reinterpret_cast<jited_function> (void_fn);
2496  }
2497 }
2498 
2500 jit_info::find (const vmap& extra_vars, const std::string& vname) const
2501 {
2502  vmap::const_iterator iter = extra_vars.find (vname);
2503  return iter == extra_vars.end () ? symbol_table::varval (vname)
2504  : *iter->second;
2505 }
2506 
2507 #endif
2508 
2509 DEFUN (jit_failcnt, args, nargout,
2510  doc: /* -*- texinfo -*-
2511 @deftypefn {} {@var{val} =} jit_failcnt ()
2512 @deftypefnx {} {@var{old_val} =} jit_failcnt (@var{new_val})
2513 @deftypefnx {} {} jit_failcnt (@var{new_val}, "local")
2514 Query or set the internal variable that counts the number of JIT fail
2515 exceptions for Octave's JIT compiler.
2516 
2517 When called from inside a function with the @qcode{"local"} option, the
2518 variable is changed locally for the function and any subroutines it calls.
2519 The original variable value is restored when exiting the function.
2520 @seealso{jit_enable, jit_startcnt, debug_jit}
2521 @end deftypefn */)
2522 {
2523 #if defined (HAVE_LLVM)
2524  return SET_INTERNAL_VARIABLE (jit_failcnt);
2525 #else
2526  octave_unused_parameter (args);
2527  octave_unused_parameter (nargout);
2528  warn_disabled_feature ("jit_failcnt", "JIT compiling");
2529  return ovl ();
2530 #endif
2531 }
2532 
2533 DEFUN (debug_jit, args, nargout,
2534  doc: /* -*- texinfo -*-
2535 @deftypefn {} {@var{val} =} debug_jit ()
2536 @deftypefnx {} {@var{old_val} =} debug_jit (@var{new_val})
2537 @deftypefnx {} {} debug_jit (@var{new_val}, "local")
2538 Query or set the internal variable that determines whether
2539 debugging/tracing is enabled for Octave's JIT compiler.
2540 
2541 When called from inside a function with the @qcode{"local"} option, the
2542 variable is changed locally for the function and any subroutines it calls.
2543 The original variable value is restored when exiting the function.
2544 @seealso{jit_enable, jit_startcnt}
2545 @end deftypefn */)
2546 {
2547 #if defined (HAVE_LLVM)
2548  return SET_INTERNAL_VARIABLE (debug_jit);
2549 #else
2550  octave_unused_parameter (args);
2551  octave_unused_parameter (nargout);
2552  warn_disabled_feature ("debug_jit", "JIT");
2553  return ovl ();
2554 #endif
2555 }
2556 
2557 DEFUN (jit_enable, args, nargout,
2558  doc: /* -*- texinfo -*-
2559 @deftypefn {} {@var{val} =} jit_enable ()
2560 @deftypefnx {} {@var{old_val} =} jit_enable (@var{new_val})
2561 @deftypefnx {} {} jit_enable (@var{new_val}, "local")
2562 Query or set the internal variable that enables Octave's JIT compiler.
2563 
2564 When called from inside a function with the @qcode{"local"} option, the
2565 variable is changed locally for the function and any subroutines it calls.
2566 The original variable value is restored when exiting the function.
2567 @seealso{jit_startcnt, debug_jit}
2568 @end deftypefn */)
2569 {
2570 #if defined (HAVE_LLVM)
2571  return SET_INTERNAL_VARIABLE (jit_enable);
2572 #else
2573  octave_unused_parameter (args);
2574  octave_unused_parameter (nargout);
2575  warn_disabled_feature ("jit_enable", "JIT");
2576  return ovl ();
2577 #endif
2578 }
2579 
2580 DEFUN (jit_startcnt, args, nargout,
2581  doc: /* -*- texinfo -*-
2582 @deftypefn {} {@var{val} =} jit_startcnt ()
2583 @deftypefnx {} {@var{old_val} =} jit_startcnt (@var{new_val})
2584 @deftypefnx {} {} jit_startcnt (@var{new_val}, "local")
2585 Query or set the internal variable that determines whether JIT compilation
2586 will take place for a specific loop.
2587 
2588 Because compilation is a costly operation it does not make sense to employ
2589 JIT when the loop count is low. By default only loops with greater than
2590 1000 iterations will be accelerated.
2591 
2592 When called from inside a function with the @qcode{"local"} option, the
2593 variable is changed locally for the function and any subroutines it calls.
2594 The original variable value is restored when exiting the function.
2595 @seealso{jit_enable, jit_failcnt, debug_jit}
2596 @end deftypefn */)
2597 {
2598 #if defined (HAVE_LLVM)
2599  return SET_INTERNAL_VARIABLE_WITH_LIMITS (jit_startcnt, 1,
2601 #else
2602  octave_unused_parameter (args);
2603  octave_unused_parameter (nargout);
2604  warn_disabled_feature ("jit_enable", "JIT");
2605  return ovl ();
2606 #endif
2607 }
virtual void visit(jit_block &)
Definition: pt-jit.cc:1502
jit_type * result(void) const
Definition: jit-typeinfo.h:295
bool Vdebug_on_error
Definition: error.cc:61
void do_return(llvm::IRBuilderD &builder, llvm::Value *rval=0, bool verify=true)
octave_base_value *(* jited_function)(octave_base_value **)
Definition: pt-jit.h:408
size_t iterator_count
Definition: pt-jit.h:186
tree_expression * operand(void)
Definition: pt-unop.h:62
void visit_colon_expression(tree_colon_expression &)
Definition: pt-jit.cc:329
const type_bound_vector & get_bounds(void) const
Definition: pt-jit.h:65
static bool Vjit_enable
Definition: pt-jit.cc:46
octave_value::assign_op op_type(void) const
Definition: pt-assign.h:81
jit_instruction * insert_after(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:352
static llvm::Value * insert_interrupt_check(llvm::IRBuilderD &bld)
Definition: jit-typeinfo.h:565
static const jit_operation & paren_subsasgn(void)
Definition: jit-typeinfo.h:540
instruction_list::iterator iterator
Definition: jit-ir.h:550
#define SET_INTERNAL_VARIABLE_WITH_LIMITS(NM, MINVAL, MAXVAL)
Definition: variables.h:132
jit_instruction * insert_before(iterator loc, jit_instruction *instr)
Definition: jit-ir.cc:344
const std::vector< std::pair< std::string, bool > > & get_arguments(void) const
Definition: pt-jit.h:258
void stash_llvm(llvm::Value *compiled)
Definition: jit-ir.h:263
bool is_range(void) const
Definition: ov.h:587
std::string next_shortcircut_result(bool inc=true)
Definition: pt-jit.h:217
std::map< std::string, llvm::Value * > arguments
Definition: pt-jit.h:274
jit_variable * dest(void) const
Definition: jit-ir.h:876
jit_value * result(void) const
Definition: jit-ir.h:1334
void simplify_phi(void)
Definition: pt-jit.cc:1979
virtual void replace_with(jit_value *value)
Definition: jit-ir.cc:168
void release_dead_phi(jit_block &ablock)
Definition: pt-jit.cc:1890
void construct_ssa(void)
Definition: pt-jit.cc:1722
jit_block * incomming(size_t i) const
Definition: jit-ir.h:971
void visit_if_command(tree_if_command &)
Definition: pt-jit.cc:541
jit_type * result_type(void) const
Definition: jit-ir.h:1382
octave_value rvalue1(int=1)
Definition: pt-const.h:73
df_iterator df_end(void) const
Definition: jit-ir.h:649
octave_value::unary_op op_type(void) const
Definition: pt-unop.h:66
OCTAVE_EXPORT octave_value_list return the value of the option it must match the dimension of the state and the relative tolerance must also be a vector of the same length tem it must match the dimension of the state and the absolute tolerance must also be a vector of the same length The local error test applied at each integration step is xample roup calculate Y_a and Y _d item Given calculate Y nd enumerate In either initial values for the given components are and initial guesses for the unknown components must also be provided as input Set this option to to solve the first or to solve the second(the default is 0, so you must provide a set of initial conditions that are consistent).If this option is set to a nonzero value
assign_op
Definition: ov.h:131
iterator end(void)
Definition: jit-ir.h:160
bool valid(void) const
Definition: jit-typeinfo.h:251
bool converting_function
Definition: pt-jit.h:276
void visit_simple_for_command(tree_simple_for_command &)
Definition: pt-jit.cc:378
static jit_type * get_any_ptr(void)
Definition: jit-typeinfo.h:457
void stash_info(jit_info *jinfo)
Definition: pt-loop.h:102
size_t use_count(void) const
Definition: jit-ir.h:570
jit_value * value
Definition: jit-ir.h:1261
void visit_simple_assignment(tree_simple_assignment &)
Definition: pt-jit.cc:754
void visit_matrix(tree_matrix &)
Definition: pt-jit.cc:645
jit_terminator * terminator(void) const
Definition: jit-ir.cc:361
const std::string & name(void) const
Definition: jit-ir.h:806
tree_expression * left_hand_side(void)
Definition: pt-assign.h:72
df_iterator df_begin(void) const
Definition: jit-ir.h:647
jit_block_list blocks
Definition: pt-jit.h:182
void push_worklist(jit_instruction *instr)
Definition: pt-jit.cc:1830
jit_call * create_checked_impl(jit_call *ret)
Definition: pt-jit.cc:1098
type op_type(void) const
Definition: pt-binop.h:168
tree_expression * switch_value(void)
Definition: pt-select.h:270
block_list breaks
Definition: pt-jit.h:236
tree_parameter_list * parameter_list(void)
Definition: ov-usr-fcn.h:377
void visit_if_clause(tree_if_clause &)
Definition: pt-jit.cc:535
llvm::Type * to_llvm(void) const
Definition: jit-typeinfo.h:152
void place_releases(void)
Definition: pt-jit.cc:1814
std::string name(void)
Definition: pt-decl.h:89
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).is_integer_type())
void visit_complex_for_command(tree_complex_for_command &)
Definition: pt-jit.cc:481
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-pr-code.cc:339
in that an updated permutation matrix is returned Note that if var
Definition: lu.cc:606
std::vector< jit_type * > argument_types
Definition: pt-jit.h:410
void visit_fcn_handle(tree_fcn_handle &)
Definition: pt-jit.cc:694
static void initialize(llvm::Module *m, llvm::ExecutionEngine *e)
jit_function_info(tree_jit &tjit, octave_user_function &fcn, const octave_value_list &ov_args)
Definition: pt-jit.cc:2203
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
void visit_return_list(tree_return_list &)
Definition: pt-jit.cc:748
jit_info(tree_jit &tjit, tree &tee)
Definition: pt-jit.cc:2364
const jit_function & overload() const
Definition: jit-ir.cc:839
octave_idx_type length(void) const
Definition: ovl.h:96
jit_block * parent(void) const
Definition: jit-ir.h:446
llvm::Function * convert_loop(llvm::Module *module, const jit_block_list &blocks, const std::list< jit_value * > &constants)
Definition: pt-jit.cc:1302
void accept(tree_walker &tw)
Definition: pt-stmt.cc:324
static bool have_breakpoints(void)
Definition: debug.h:119
llvm::Value * to_llvm(void) const
Definition: jit-ir.h:257
jit_instruction * prepend(jit_instruction *instr)
Definition: jit-ir.cc:312
jit_block * block
Definition: pt-jit.h:178
llvm::Type * type_llvm(void) const
Definition: jit-ir.h:217
llvm::Module * module
Definition: pt-jit.h:385
void visit_statement_list(tree_statement_list &)
Definition: pt-pr-code.cc:901
jit_function convert_function(llvm::Module *module, const jit_block_list &blocks, const std::list< jit_value * > &constants, octave_user_function &fcn, const std::vector< jit_type * > &args)
Definition: pt-jit.cc:1352
void release_temp(jit_block &ablock, std::set< jit_value * > &temp)
Definition: pt-jit.cc:1925
type_bound_vector bounds
Definition: pt-jit.h:162
void visit_constant(tree_constant &)
Definition: pt-jit.cc:669
OCTAVE_EXPORT octave_value_list return the value of the option it must match the dimension of the state and the relative tolerance must also be a vector of the same length tem it must match the dimension of the state and the absolute tolerance must also be a vector of the same length The local error test applied at each integration step is xample roup so it is best to provide a consistent set and leave this option set to zero tem it may help to set this parameter to a nonzero value it is probably best to try leaving this option set to zero first
Definition: DASSL-opts.cc:419
jit_instruction * resolve(tree_index_expression &exp, jit_value *extra_arg=0, bool lhs=false)
Definition: pt-jit.cc:1181
llvm::PassManager * module_pass_manager
Definition: pt-jit.h:390
bool is_default_case(void)
Definition: pt-select.h:187
static bool execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.cc:2026
void remove(void)
Definition: jit-ir.cc:204
tree_command * command(void)
Definition: pt-stmt.h:84
cr
Definition: mappers.cc:1852
Definition: Range.h:33
void visit_if_command_list(tree_if_command_list &)
Definition: pt-jit.cc:549
binary_op
Definition: ov.h:89
llvm::BasicBlock * prelude
Definition: pt-jit.h:282
static const jit_operation & for_init(void)
Definition: jit-typeinfo.h:515
void protect_var(T &var)
T * append(T *instr)
Definition: jit-ir.h:590
#define DEFUN(name, args_name, nargout_name, doc)
Definition: defun.h:46
size_t trip_count(const octave_value &bounds) const
Definition: pt-jit.cc:2167
void error(const char *fmt,...)
Definition: error.cc:570
symbol_table::scope_id scope(void)
Definition: ov-usr-fcn.h:249
iterator end(void)
Definition: jit-ir.h:631
static const jit_operation & release(void)
Definition: jit-typeinfo.h:495
is greater than zero
Definition: load-path.cc:2339
std::string name(void) const
Definition: ov-fcn.h:163
#define SET_INTERNAL_VARIABLE(NM)
Definition: variables.h:126
bool prune(void)
Definition: jit-ir.cc:600
bool is_special_expr(void) const
Definition: ov-usr-fcn.h:321
elt_type & back(void)
Definition: base-list.h:98
octave_value varval(context_id context=xdefault_context) const
Definition: symtab.h:570
jit_type * type(void) const
Definition: jit-ir.h:215
tree_switch_case_list * case_list(void)
Definition: pt-select.h:272
llvm::Module * get_module(void) const
Definition: pt-jit.h:364
bool known(void) const
Definition: jit-util.h:95
jit_block * first_use_block(void)
Definition: jit-ir.cc:153
static binary_op assign_op_to_binary_op(assign_op)
Definition: ov.cc:395
std::vector< jit_magic_end::context > end_context
Definition: pt-jit.h:184
std::vector< std::pair< std::string, bool > > arguments
Definition: pt-jit.h:443
jit_block * dom_successor(size_t idx) const
Definition: jit-ir.h:683
void stash_info(jit_function_info *info)
Definition: ov-usr-fcn.h:410
iterator begin(void)
Definition: jit-ir.h:156
std::list< tree_decl_elt * >::iterator iterator
Definition: base-list.h:40
iterator erase(iterator iter)
Definition: jit-ir.h:164
void visit_argument_list(tree_argument_list &)
Definition: pt-jit.cc:253
const jit_function & overload(void) const
Definition: jit-ir.h:1301
bool execute(const octave_value_list &ov_args, octave_value_list &retval) const
Definition: pt-jit.cc:2321
octave_idx_type nelem
Definition: jit-typeinfo.h:63
tree_statement_list * commands(void)
Definition: pt-select.h:63
void add_incomming(jit_block *from, jit_value *value)
Definition: jit-ir.h:964
bool do_execute(tree_simple_for_command &cmd, const octave_value &bounds)
Definition: pt-jit.cc:2098
void visit_global_command(tree_global_command &)
Definition: pt-jit.cc:354
void visit_postfix_expression(tree_postfix_expression &)
Definition: pt-jit.cc:712
void erase(void)
static const jit_operation & for_check(void)
Definition: jit-typeinfo.h:520
static const jit_operation & paren_subsref(void)
Definition: jit-typeinfo.h:535
void compute_df(void)
Definition: jit-ir.h:673
tree_expression * expression(void)
Definition: pt-idx.h:74
tree_expression * case_label(void)
Definition: pt-select.h:191
void visit_anon_fcn_handle(tree_anon_fcn_handle &)
Definition: pt-jit.cc:247
s
Definition: file-io.cc:2682
static llvm::IRBuilder builder(llvm::getGlobalContext())
void stash_info(jit_info *jinfo)
Definition: pt-loop.h:232
bool visited(size_t avisit_count)
Definition: jit-ir.h:733
void visit_parameter_list(tree_parameter_list &)
Definition: pt-jit.cc:706
static llvm::Type * get_scalar_llvm(void)
Definition: jit-typeinfo.h:452
void add_method(T *obj, void(T::*method)(void))
const std::string & name(void) const
Definition: jit-ir.h:1296
i e
Definition: data.cc:2724
std::map< std::string, const octave_value * > vmap
Definition: pt-jit.h:419
void create_dom_tree(void)
Definition: jit-ir.h:678
jit_block_list & get_blocks(void)
Definition: pt-jit.h:63
static octave_value find_function(const std::string &name, const octave_value_list &args=octave_value_list(), bool local_funcs=true)
Definition: symtab.cc:1276
std::string next_for_bounds(bool inc=true)
Definition: pt-jit.h:214
std::string type_tags(void)
Definition: pt-idx.h:78
double base
Definition: jit-typeinfo.h:60
jit_value * overwrite(void) const
Definition: jit-ir.h:907
static tree_jit & instance(void)
Definition: pt-jit.cc:2045
static octave_value varval(const std::string &name, scope_id scope=xcurrent_scope, context_id context=xdefault_context)
Definition: symtab.h:1373
void convert(const jit_block_list &blocks, const std::list< jit_value * > &constants)
Definition: pt-jit.cc:1398
void visit_prefix_expression(tree_prefix_expression &)
Definition: pt-jit.cc:730
void visit_switch_case(tree_switch_case &)
Definition: pt-jit.cc:826
bool initialize(void)
Definition: pt-jit.cc:2052
octave_value arg
Definition: pr-output.cc:3440
virtual bool needs_release(void) const
Definition: jit-ir.h:243
octave_function * fcn
Definition: ov-class.cc:1743
void do_construct_ssa(jit_block &block, size_t avisit_count)
Definition: pt-jit.cc:1769
const jit_function & overload(void) const
Definition: jit-ir.h:1329
jit_info * get_info(void) const
Definition: pt-loop.h:97
static jit_type * get_range(void)
Definition: jit-typeinfo.h:459
void visit_cell(tree_cell &)
Definition: pt-jit.cc:651
void visit_statement(tree_statement &)
Definition: pt-jit.cc:775
void push_back(jit_block *b)
Definition: jit-ir.cc:122
jit_value * src(void) const
Definition: jit-ir.h:912
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-jit.cc:505
llvm::Value * call(llvm::IRBuilderD &builder, const std::vector< jit_value * > &in_args) const
tree_expression * increment(void)
Definition: pt-colon.h:91
void visit_index_expression(tree_index_expression &)
Definition: pt-jit.cc:639
static const size_t NO_ID
Definition: jit-ir.h:556
tree_if_command_list * cmd_list(void)
Definition: pt-select.h:137
std::list< jit_instruction * > worklist
Definition: pt-jit.h:319
bool execute(const vmap &extra_vars=vmap()) const
Definition: pt-jit.cc:2383
static llvm::LLVMContext & context
Definition: pt-jit.cc:103
static symbol_record find_symbol(const std::string &name, scope_id scope=xcurrent_scope)
Definition: symtab.h:1278
jit_block_list & blocks
Definition: pt-jit.h:316
tree_statement_list * body(void)
Definition: pt-loop.h:214
JNIEnv void * args
Definition: ov-java.cc:67
jit_value * result
Definition: pt-jit.h:172
bool has_magic_end(void) const
Definition: pt-id.h:61
tree_jit(void)
Definition: pt-jit.cc:2019
static const jit_operation & cast(jit_type *result)
Definition: jit-typeinfo.h:550
void visit_octave_user_script(octave_user_script &)
Definition: pt-jit.cc:487
static jit_type * get_complex(void)
Definition: jit-typeinfo.h:470
void finish_breaks(jit_block *dest, const block_list &lst)
Definition: pt-jit.cc:1290
iterator remove(iterator iter)
Definition: jit-ir.h:610
done
Definition: syscalls.cc:248
bool alive(const jit_block *asuccessor) const
Definition: jit-ir.h:1053
bool print_result(void) const
Definition: pt-exp.h:99
size_t short_count
Definition: pt-jit.h:188
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an so it may be a literal a variable name
Definition: input.cc:871
iterator end(void)
Definition: base-list.h:86
jit_block * back(void) const
Definition: jit-ir.h:154
static int Vjit_failcnt
Definition: pt-jit.cc:50
tree_expression * right_hand_side(void)
Definition: pt-assign.h:74
jit_factory & factory
Definition: pt-jit.h:317
std::list< tree_argument_list * > arg_lists(void)
Definition: pt-idx.h:76
bool Vdebug_on_interrupt
Definition: sighandlers.cc:70
tree_expression * condition(void)
Definition: pt-select.h:61
OCTAVE_EXPORT octave_value_list return the number of command line arguments passed to Octave If called with the optional argument the function xample nargout(@histc)
Definition: ov-usr-fcn.cc:935
void visit_persistent_command(tree_persistent_command &)
Definition: pt-jit.cc:360
bool is_persistent(void) const
Definition: symtab.h:609
jit_block & entry_block(void)
Definition: pt-jit.h:329
void visit_identifier(tree_identifier &)
Definition: pt-jit.cc:517
const jit_function & overload(void) const
Definition: jit-ir.h:1165
static const jit_operation & make_range(void)
Definition: jit-typeinfo.h:530
block_list continues
Definition: pt-jit.h:237
symbol_table::scope_id scope
Definition: pt-jit.h:167
type_bound_vector bounds
Definition: pt-jit.h:444
tree_expression * control_expr(void)
Definition: pt-loop.h:210
static uint32_t * next
Definition: randmtzig.cc:183
variable check_variable(void) const
Definition: jit-ir.h:1219
bool is_global(void) const
Definition: symtab.h:606
jit_infer(jit_factory &afactory, jit_block_list &ablocks, const variable_map &avmap)
Definition: pt-jit.cc:1653
virtual void construct_ssa(void)
Definition: jit-ir.h:435
tree_parameter_list * return_list(void)
Definition: ov-usr-fcn.h:379
void accept(tree_walker &tw)
Definition: pt-stmt.cc:185
jit_const_index * index
Definition: jit-ir.h:1262
bool converting_function
Definition: pt-jit.h:164
std::list< jit_block * > block_list
Definition: pt-jit.h:235
std::string name(void) const
Definition: pt-id.h:67
Range range_value(void) const
Definition: ov.h:923
void append_users(jit_value *v)
Definition: pt-jit.cc:1696
jit_convert::variable_map variable_map
Definition: pt-jit.h:305
jit_factory factory
Definition: pt-jit.h:169
void visit_do_until_command(tree_do_until_command &)
Definition: pt-jit.cc:1019
jit_block * front(void) const
Definition: jit-ir.h:166
jit_block * successor(size_t idx=0) const
Definition: jit-ir.h:1030
bool match(const octave_value_list &ov_args) const
Definition: pt-jit.cc:2347
octave_idx_type numel(void) const
Definition: Range.h:85
void visit_octave_user_function_header(octave_user_function &)
Definition: pt-jit.cc:499
bool in_worklist(void) const
Definition: jit-ir.h:198
llvm::ExecutionEngine * engine
Definition: pt-jit.h:393
void append_users_term(jit_terminator *term)
Definition: pt-jit.cc:1703
std::vector< std::pair< std::string, bool > > argument_vec
Definition: pt-jit.h:271
void infer(void)
Definition: pt-jit.cc:1658
void warn_disabled_feature(const std::string &fcn, const std::string &feature, const std::string &pkg)
Definition: errwarn.cc:308
bool artificial(void) const
Definition: jit-ir.h:920
static const jit_operation & binary_op(int op)
Definition: jit-typeinfo.h:478
context resolve_context(void) const
Definition: jit-ir.cc:799
tree_expression * limit(void)
Definition: pt-colon.h:89
void visit_unwind_protect_command(tree_unwind_protect_command &)
Definition: pt-jit.cc:951
std::ostream & print(std::ostream &os, const std::string &header) const
Definition: jit-ir.cc:101
is false
Definition: cellfun.cc:398
octave_value retval
Definition: data.cc:6294
virtual bool infer(void)
Definition: jit-ir.cc:725
#define panic_impossible()
Definition: error.h:40
static jit_type * get_scalar(void)
Definition: jit-typeinfo.h:450
jit_convert(tree &tee, jit_type *for_bounds=0)
Definition: pt-jit.cc:114
~jit_info(void)
Definition: pt-jit.cc:2376
void visit_funcall(tree_funcall &)
Definition: pt-jit.cc:700
void label(void)
Definition: jit-ir.cc:91
tree_expression * lhs(void)
Definition: pt-binop.h:97
tree_expression * left_hand_side(void)
Definition: pt-loop.h:208
void remove_dead()
Definition: pt-jit.cc:1840
jit_value * visit(tree *tee)
Definition: pt-jit.h:231
jit_value * argument(size_t i) const
Definition: jit-ir.h:367
static void assign(const std::string &name, const octave_value &value=octave_value(), scope_id scope=xcurrent_scope, context_id context=xdefault_context, bool force_add=false)
Definition: symtab.h:1330
static const jit_operation & create_undef(void)
Definition: jit-typeinfo.h:581
llvm::Value * cond_llvm(void) const
Definition: jit-ir.h:1104
llvm::PHINode * to_llvm(void) const
Definition: jit-ir.cc:665
idx type
Definition: ov.cc:3129
jit_const_index * count
Definition: jit-ir.h:1263
static llvm::Value * insert_error_check(llvm::IRBuilderD &bld)
Definition: jit-typeinfo.h:560
void visit_switch_case_list(tree_switch_case_list &)
Definition: pt-jit.cc:832
jit_function_info * get_info(void)
Definition: ov-usr-fcn.h:408
size_t argument_count(void) const
Definition: jit-ir.h:409
tree_statement_list * commands(void)
Definition: pt-select.h:193
octave_value::binary_op op_type(void) const
Definition: pt-binop.h:95
void visit_return_command(tree_return_command &)
Definition: pt-jit.cc:742
tree_expression * special_expr(void)
Definition: ov-usr-fcn.cc:652
void stash_argument(size_t i, jit_value *arg)
Definition: jit-ir.h:397
jit_value * do_assign(tree_expression *exp, jit_value *rhs, bool artificial=false)
Definition: pt-jit.cc:1239
bool has_top(void) const
Definition: jit-ir.h:810
void visit_switch_command(tree_switch_command &)
Definition: pt-jit.cc:838
With real return the complex result
Definition: data.cc:3375
void finish_phi(jit_phi *phi)
Definition: pt-jit.cc:1438
jit_factory & get_factory(void)
Definition: pt-jit.h:67
void stash_in_worklist(bool ain_worklist)
Definition: jit-ir.h:203
llvm::BasicBlock * to_llvm(void) const
Definition: jit-ir.cc:392
variable_map vmap
Definition: pt-jit.h:190
df_set::const_iterator df_iterator
Definition: jit-ir.h:554
bool takes_varargs(void) const
Definition: pt-misc.h:73
size_t for_bounds_count
Definition: pt-jit.h:187
static bool Vdebug_jit
Definition: pt-jit.cc:44
void visit_multi_assignment(tree_multi_assignment &)
Definition: pt-jit.cc:657
static llvm::Type * get_index_llvm(void)
Definition: jit-typeinfo.h:467
std::string next_iterator(bool inc=true)
Definition: pt-jit.h:211
virtual bool infer(void)
Definition: jit-ir.cc:683
bool enabled(void)
Definition: pt-jit.cc:2157
octave::unwind_protect frame
Definition: graphics.cc:11584
virtual std::string name(void) const
Definition: pt-exp.h:103
void grab(void)
Definition: ov-base.h:800
std::string str_print_code(void)
Definition: pt.cc:40
static octave_idx_type fout(const octave_idx_type &lsize, const double &alpha, const double &beta, const double &, const double &p)
Definition: qz.cc:124
virtual bool infer(void)
Definition: jit-ir.h:440
charNDArray max(char d, const charNDArray &m)
Definition: chNDArray.cc:228
size_t use_count(void) const
Definition: jit-util.h:125
static const jit_operation & unary_op(int op)
Definition: jit-typeinfo.h:483
void compile(tree_jit &tjit, tree &tee, jit_type *for_bounds=0)
Definition: pt-jit.cc:2437
void visit_octave_user_function_trailer(octave_user_function &)
Definition: pt-pr-code.cc:429
static const jit_function & get_release(jit_type *type)
Definition: jit-typeinfo.h:500
llvm::BasicBlock * incomming_llvm(size_t i) const
Definition: jit-ir.h:976
jit_info * get_info(void) const
Definition: pt-loop.h:227
std::pair< jit_type *, std::string > type_bound
Definition: pt-jit.h:43
const variable_map & vmap
Definition: pt-jit.h:318
void visit_no_op_command(tree_no_op_command &)
Definition: pt-jit.cc:663
tree_expression * rhs(void)
Definition: pt-binop.h:98
NODE_T * first_use(void) const
Definition: jit-util.h:123
static int Vjit_startcnt
Definition: pt-jit.cc:48
bool is_else_clause(void)
Definition: pt-select.h:59
std::set< jit_block * > df_set
Definition: jit-ir.h:553
jit_value * result(void) const
Definition: jit-ir.h:1377
void visit_decl_elt(tree_decl_elt &)
Definition: pt-jit.cc:366
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
size_t size(void) const
Definition: base-list.h:49
size_t successor_count(void) const
Definition: jit-ir.h:1062
static const jit_operation & print_value(void)
Definition: jit-typeinfo.h:510
OCTAVE_EXPORT octave_value_list or N dimensional array whose elements are all equal to the IEEE symbol zero divided by nd tex zero divided by nd ifnottex and any operation involving another NaN value(5+NaN).Note that NaN always compares not equal to NaN(NaN!
void pop_all(void)
Definition: jit-ir.cc:504
tree_expression * expression(void)
Definition: pt-stmt.h:86
double inc
Definition: jit-typeinfo.h:62
Definition: pt.h:39
void visit_break_command(tree_break_command &)
Definition: pt-jit.cc:322
void compute_idom(jit_block &entry_block)
Definition: jit-ir.h:663
Complex complex_value(bool frc_str_conv=false) const
Definition: ov.h:799
const value_list & constants(void) const
Definition: jit-ir.h:110
bool match(const vmap &extra_vars=vmap()) const
Definition: pt-jit.cc:2417
void optimize(llvm::Function *fn)
Definition: pt-jit.cc:2180
PASS_T value(void) const
Definition: jit-ir.h:522
void accept(tree_walker &tw)
Definition: pt-select.cc:81
size_t id(void) const
Definition: jit-ir.h:642
elt_type & front(void)
Definition: base-list.h:97
llvm::Value * argument_llvm(size_t i) const
Definition: jit-ir.h:372
b
Definition: cellfun.cc:398
ots The first example below creates an uninitialized object
Definition: ov-java.cc:2837
void visit_continue_command(tree_continue_command &)
Definition: pt-jit.cc:347
bool is_undefined(void) const
Definition: ov.h:539
std::list< jit_block * >::iterator iterator
Definition: jit-ir.h:151
static void reset_ids(void)
Definition: jit-ir.h:362
llvm::BasicBlock * new_block(const std::string &aname="body", llvm::BasicBlock *insert_before=0)
void visit_binary_expression(tree_binary_expression &)
Definition: pt-jit.cc:259
iterator begin(void)
Definition: jit-ir.h:627
void visit_decl_init_list(tree_decl_init_list &)
Definition: pt-jit.cc:372
void visit_octave_user_function(octave_user_function &)
Definition: pt-jit.cc:493
virtual bool is_assignment_expression(void) const
Definition: pt-exp.h:65
jit_block * successor(size_t i) const
Definition: jit-ir.cc:378
llvm::ExecutionEngine * engine
Definition: pt-jit.h:439
llvm::FunctionPassManager * pass_manager
Definition: pt-jit.h:391
static const jit_operation & grab(void)
Definition: jit-typeinfo.h:488
ColumnVector imag(const ComplexColumnVector &a)
Definition: dColVector.cc:142
const std::string & name(void) const
Definition: jit-ir.h:583
jit_block & final_block(void)
Definition: pt-jit.h:331
std::string next_name(const char *prefix, size_t &count, bool inc)
Definition: pt-jit.cc:1171
jit_block * entry_block
Definition: pt-jit.h:174
llvm::ExecutionEngine * get_engine(void) const
Definition: pt-jit.h:362
jit_block * maybe_split(jit_factory &factory, jit_block_list &blocks, jit_block *asuccessor)
Definition: jit-ir.cc:536
double limit
Definition: jit-typeinfo.h:61
const std::string & name(void) const
Definition: jit-ir.h:1324
OCTAVE_EXPORT octave_value_list it applies a binary function and expands as necessary singleton dimensions in either input argument function
Definition: bsxfun.cc:336
static jit_type * get_any(void)
Definition: jit-typeinfo.h:446
llvm::Value * argument(llvm::IRBuilderD &builder, size_t idx) const
tree_expression * base(void)
Definition: pt-colon.h:87
tree_statement_list * body(void)
Definition: pt-loop.h:84
jit_instruction * back(void)
Definition: jit-ir.h:746
void visit_while_command(tree_while_command &)
Definition: pt-jit.cc:957
std::complex< double > Complex
Definition: oct-cmplx.h:31
void(* jited_function)(octave_base_value **)
Definition: pt-jit.h:433
void initialize(symbol_table::scope_id s)
Definition: pt-jit.cc:1082
llvm::Function * llvm_function
Definition: pt-jit.h:441
static jit_type * type_of(const octave_value &ov)
Definition: jit-typeinfo.h:473
octave_base_value * internal_rep(void) const
Definition: ov.h:1299
ColumnVector real(const ComplexColumnVector &a)
Definition: dColVector.cc:136
double double_value(bool frc_str_conv=false) const
Definition: ov.h:775
virtual void push_variable(void)
Definition: jit-ir.h:431
void mark_alive(void)
Definition: jit-ir.h:575
jit_function creating
Definition: pt-jit.h:279
T * create(void)
Definition: jit-ir.h:113
static llvm::Value * create_complex(llvm::Value *real, llvm::Value *imag)
Definition: jit-typeinfo.h:586
llvm::Function * to_llvm(void) const
Definition: jit-typeinfo.h:286
NODE_T * next(void) const
Definition: jit-util.h:169
tree_statement_list * body(void)
Definition: ov-usr-fcn.h:381
jit_instruction * user(void) const
Definition: jit-ir.h:310
void visit_function_def(tree_function_def &)
Definition: pt-jit.cc:511
the second is matched to the second specifier and placed in the second column and so forth If there are more words than specifiers then the process is repeated until all words have been processed or the limit imposed by any(non-whitespace) text in the format that is not one of these specifiers is considered a literal.If there is a literal between two format specifiers then that same literal must appear in the input stream between the matching words.The following specifiers are valid
Definition: file-io.cc:1491
jit_value * top(void) const
Definition: jit-ir.h:815
llvm::BasicBlock * successor_llvm(size_t idx=0) const
Definition: jit-ir.h:1035
unary_op
Definition: ov.h:76
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:854
void visit_statement_list(tree_statement_list &)
Definition: pt-jit.cc:813
octave_value find(const vmap &extra_vars, const std::string &vname) const
Definition: pt-jit.cc:2500
virtual void accept(tree_walker &tw)=0
size_t successor_count(void) const
Definition: jit-ir.cc:385
dim_vector dv
Definition: sub2ind.cc:263
const variable_map & get_variable_map(void) const
Definition: pt-jit.h:71
void visit_try_catch_command(tree_try_catch_command &)
Definition: pt-jit.cc:945
static const jit_operation & for_index(void)
Definition: jit-typeinfo.h:525
virtual bool is_identifier(void) const
Definition: pt-exp.h:61
bool alive(void) const
Definition: jit-ir.h:573
jit_variable * find_variable(const std::string &vname) const
Definition: pt-jit.cc:1114
size_t dom_successor_count(void) const
Definition: jit-ir.h:688
iterator begin(void)
Definition: base-list.h:83
return octave_value(v1.char_array_value().concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string())? '\'': '"'))
jit_variable * get_variable(const std::string &vname)
Definition: pt-jit.cc:1122
static const jit_operation & logically_true(void)
Definition: jit-typeinfo.h:545
void mark_artificial(void)
Definition: jit-ir.h:922
static scope_id current_scope(void)
Definition: symtab.h:1163
jit_call * create_checked(const ARG0 &arg0)
Definition: pt-jit.h:60
jit_block * final_block
Definition: pt-jit.h:176
const std::vector< jit_use > & arguments(void) const
Definition: jit-ir.h:425
tree_expression * condition(void)
Definition: pt-loop.h:82
static const jit_operation & destroy(void)
Definition: jit-typeinfo.h:505
~tree_jit(void)
Definition: pt-jit.cc:2022
jit_variable * create_variable(const std::string &vname, jit_type *type, bool isarg=true)
Definition: pt-jit.cc:1148