25 #define __STDC_LIMIT_MACROS
26 #define __STDC_CONSTANT_MACROS
49 #include <llvm/Analysis/CallGraph.h>
50 #include <llvm/Analysis/Passes.h>
51 #include <llvm/Analysis/Verifier.h>
52 #include <llvm/Bitcode/ReaderWriter.h>
53 #include <llvm/ExecutionEngine/ExecutionEngine.h>
54 #include <llvm/ExecutionEngine/JIT.h>
55 #include <llvm/PassManager.h>
57 #ifdef HAVE_LLVM_IR_FUNCTION_H
58 #include <llvm/IR/LLVMContext.h>
59 #include <llvm/IR/Module.h>
61 #include <llvm/LLVMContext.h>
62 #include <llvm/Module.h>
65 #ifdef HAVE_LLVM_SUPPORT_IRBUILDER_H
66 #include <llvm/Support/IRBuilder.h>
67 #elif defined(HAVE_LLVM_IR_IRBUILDER_H)
68 #include <llvm/IR/IRBuilder.h>
70 #include <llvm/IRBuilder.h>
73 #include <llvm/Support/raw_os_ostream.h>
74 #include <llvm/Support/TargetSelect.h>
76 #ifdef HAVE_LLVM_IR_DATALAYOUT_H
77 #include <llvm/IR/DataLayout.h>
78 #elif defined(HAVE_LLVM_DATALAYOUT_H)
79 #include <llvm/DataLayout.h>
81 #include <llvm/Target/TargetData.h>
84 #include <llvm/Transforms/IPO.h>
85 #include <llvm/Transforms/Scalar.h>
87 static llvm::IRBuilder<>
builder (llvm::getGlobalContext ());
89 static llvm::LLVMContext&
context = llvm::getGlobalContext ();
99 : converting_function (false)
120 for (variable_map::iterator iter =
vmap.begin (); iter !=
vmap.end (); ++iter)
123 const std::string& name = var->
name ();
124 if (name.size () && name[0] !=
'#')
132 const std::vector<jit_type *>& args)
133 : converting_function (true)
139 if (plist && plist->takes_varargs ())
148 for (
size_t i = 0; i < args.size (); ++i, ++piter)
150 if (piter == plist->end ())
154 std::string name = elt->
name ();
160 bool all_breaking =
false;
170 retval =
visit (expr);
177 "anonymous functions");
180 return_value = retvar;
205 if (! return_value && rlist && rlist->
size () == 1)
213 for (variable_map::iterator iter =
vmap.begin (); iter !=
vmap.end (); ++iter)
215 if (iter->second != return_value)
254 vmap[short_name] = short_result;
322 increment =
visit (tinc);
327 base, limit, increment));
379 vmap[iter_name] = iterator;
410 bool all_breaking =
false;
452 block = interrupt_check;
541 std::vector<jit_block *> entry_blocks (lst.
size () + 1 - last_else);
542 std::vector<jit_block *> branch_blocks (lst.
size (), 0);
543 entry_blocks[0] =
block;
548 for (
size_t i = 1; iter != lst.
end (); ++iter, ++i)
559 entry_blocks[entry_blocks.size () - 1] = tail;
568 size_t num_incomming = 0;
570 for (
size_t i = 0; iter != lst.
end (); ++iter, ++i)
573 block = entry_blocks[i];
590 entry_blocks[i + 1]);
607 current_breaks.splice (current_breaks.end (),
breaks);
608 current_continues.splice (current_continues.end (),
continues);
614 if (num_incomming || ! last_else)
765 bool do_bind_ans =
false;
771 do_bind_ans = (!
id->is_variable ());
850 assert (expr &&
"While expression can not be null");
862 bool all_breaking =
false;
867 loop_body->
accept (*
this);
886 block = interrupt_check;
938 variable_map::const_iterator iter;
939 iter =
vmap.find (vname);
940 return iter !=
vmap.end () ? iter->second : 0;
986 return vmap[vname] = var;
992 std::stringstream ss;
993 ss << prefix << count;
1004 if (! (type.size () == 1 && type[0] ==
'('))
1007 std::list<tree_argument_list *> args = exp.
arg_lists ();
1008 if (args.size () != 1)
1010 "tree_index_expression");
1016 if (arg_list->
size () < 1)
1029 object =
visit (tree_object);
1031 size_t narg = arg_list->
size ();
1033 bool have_extra = extra_arg;
1034 std::vector<jit_value *> call_args (narg + 1 + have_extra);
1035 call_args[0] = object;
1037 for (
size_t idx = 0; iter != arg_list->
end (); ++idx, ++iter)
1041 &std::vector<jit_magic_end::context>::pop_back);
1045 call_args[idx + 1] =
visit (*iter);
1049 call_args[call_args.size () - 1] = extra_arg;
1063 if (isa<tree_identifier> (exp))
1066 = dynamic_cast<tree_index_expression *> (exp))
1069 do_assign (idx->expression (), new_object,
true);
1080 bool print,
bool artificial)
1111 for (block_list::const_iterator iter = lst.begin (); iter != lst.end ();
1123 const std::list<jit_value *>& constants)
1131 iter != entry_block->
end (); ++iter)
1133 = dynamic_cast<jit_extract_argument *> (*iter))
1134 argument_vec.push_back (std::make_pair (extract->name (),
true));
1140 llvm::Type *arg_type = any->
to_llvm ();
1141 arg_type = arg_type->getPointerTo ();
1142 llvm::FunctionType *ft;
1143 ft = llvm::FunctionType::get (llvm::Type::getVoidTy (context), arg_type,
1145 function = llvm::Function::Create (ft, llvm::Function::ExternalLinkage,
1150 prelude = llvm::BasicBlock::Create (context,
"prelude",
function);
1153 llvm::Value *
arg =
function->arg_begin ();
1156 llvm::Value *loaded_arg =
builder.CreateConstInBoundsGEP1_32 (arg, i);
1164 function->eraseFromParent ();
1175 const std::list<jit_value *>& constants,
1177 const std::vector<jit_type *>& args)
1199 for (
size_t i = 0; i < args.size () && piter != pend; ++i, ++piter)
1202 std::string arg_name = elt->
name ();
1211 function->eraseFromParent ();
1220 const std::list<jit_value *>& constants)
1222 std::list<jit_block *>::const_iterator biter;
1223 for (biter = blocks.
begin (); biter != blocks.
end (); ++biter)
1226 llvm::BasicBlock *block = llvm::BasicBlock::Create (context,
1236 for (std::list<jit_value *>::const_iterator iter = constants.begin ();
1237 iter != constants.end (); ++iter)
1238 if (! isa<jit_instruction> (*iter))
1242 for (biter = blocks.
begin (); biter != blocks.
end (); ++biter)
1246 for (biter = blocks.
begin (); biter != blocks.
end (); ++biter)
1250 piter != block.
end () && isa<jit_phi> (*piter); ++piter)
1261 llvm::PHINode *llvm_phi = phi->
to_llvm ();
1292 llvm::Value *
real = llvm::ConstantFP::get (scalar_t, value.real ());
1293 llvm::Value *
imag = llvm::ConstantFP::get (scalar_t, value.imag ());
1305 llvm::StructType *stype = llvm::cast<llvm::StructType>(cr.
type_llvm ());
1310 llvm::Constant *constants[4];
1311 constants[0] = llvm::ConstantFP::get (scalar_t, rng.
base);
1312 constants[1] = llvm::ConstantFP::get (scalar_t, rng.
limit);
1313 constants[2] = llvm::ConstantFP::get (scalar_t, rng.
inc);
1314 constants[3] = llvm::ConstantInt::get (idx, rng.
nelem);
1316 llvm::Value *as_llvm;
1317 as_llvm = llvm::ConstantStruct::get (stype,
1318 llvm::makeArrayRef (constants, 4));
1325 llvm::BasicBlock *block = b.
to_llvm ();
1326 builder.SetInsertPoint (block);
1352 std::vector<jit_value *> args (call.
arguments ().size ());
1353 for (
size_t i = 0; i < args.size (); ++i)
1370 arg =
builder.CreateLoad (arg);
1407 llvm::PHINode *node = llvm::PHINode::Create (phi.
type_llvm (),
1451 if (isa<jit_assign_base> (overwrite))
1476 : blocks (ablocks), factory (afactory), vmap (avmap) { }
1485 for (std::list<jit_value *>::const_iterator iter = constants.begin ();
1486 iter != constants.end (); ++iter)
1503 if (
jit_terminator *term = dynamic_cast<jit_terminator *> (next))
1528 if (term->
alive (i))
1532 iter != succ->
end () && isa<jit_phi> (*iter); ++iter)
1551 for (variable_map::const_iterator iter =
vmap.begin (); iter !=
vmap.end ();
1555 std::list<jit_block *> ssa_worklist;
1556 iter->second->use_blocks (visited);
1557 ssa_worklist.insert (ssa_worklist.begin (), visited.begin (),
1560 while (ssa_worklist.size ())
1563 ssa_worklist.pop_front ();
1566 diter != b->
df_end (); ++diter)
1569 if (! added_phi.count (dblock))
1574 added_phi.insert (dblock);
1577 if (! visited.count (dblock))
1579 ssa_worklist.push_back (dblock);
1580 visited.insert (dblock);
1592 if (ablock.
visited (avisit_count))
1610 iter != finish->
end () && isa<jit_phi> (*iter);)
1622 assert (var->
name ().size () && var->
name ()[0] ==
'#');
1637 std::set<jit_value *> temporaries;
1670 iter != b->
end () && isa<jit_phi> (*iter);)
1714 while (iter != ablock.
end () && isa<jit_phi> (*iter))
1720 if (phi->
use_count () == 1 && isa<jit_assign> (use->
user ()))
1758 if (fu_block && fu_block != &ablock && instr->
needs_release ())
1759 temp.insert (instr);
1762 if (isa<jit_call> (instr))
1781 if (! temp.size () || ! isa<jit_error_check> (ablock.
terminator ()))
1788 for (std::set<jit_value *>::const_iterator iter = temp.begin ();
1789 iter != temp.end (); ++iter)
1807 iter != ablock.
end () && isa<jit_phi> (*iter); ++iter)
1881 llvm::InitializeNativeTarget ();
1882 module =
new llvm::Module (
"octave", context);
1895 #ifdef HAVE_LLVM_DATALAYOUT
1900 pass_manager->add (llvm::createCFGSimplificationPass ());
1901 pass_manager->add (llvm::createBasicAliasAnalysisPass ());
1902 pass_manager->add (llvm::createPromoteMemoryToRegisterPass ());
1903 pass_manager->add (llvm::createInstructionCombiningPass ());
1906 pass_manager->add (llvm::createCFGSimplificationPass ());
1922 extra_vars[
"#for_bounds0"] = &bounds;
1925 if (! info || ! info->
match (extra_vars))
1927 if (tc < static_cast<size_t> (Vjit_startcnt))
1931 info =
new jit_info (*
this, cmd, bounds);
1935 return info->
execute (extra_vars);
1945 if (! info || ! info->
match ())
1963 if (! info || ! info->
match (args))
1970 return info->
execute (args, retval);
1989 return rng.
nelem ();
2001 llvm::verifyModule (*
module);
2009 llvm::raw_fd_ostream
fout (
"test.bc", error,
2010 llvm::raw_fd_ostream::F_Binary);
2011 llvm::WriteBitcodeToFile (
module, fout);
2019 : argument_types (ov_args.
length ()), function (0)
2021 size_t nargs = ov_args.
length ();
2022 for (
size_t i = 0; i < nargs; ++i)
2039 std::cout <<
"-------------------- Compiling function ";
2040 std::cout <<
"--------------------\n";
2046 blocks.
print (std::cout,
"octave jit ir");
2058 std::cout <<
"-------------------- raw function ";
2059 std::cout <<
"--------------------\n";
2060 std::cout << *raw_fn.
to_llvm () << std::endl;
2061 llvm::verifyFunction (*raw_fn.
to_llvm ());
2064 std::string wrapper_name = fcn.
name () +
"_wrapper";
2068 any_t, wrapper_args);
2070 llvm::BasicBlock *wrapper_body = wrapper.
new_block ();
2071 builder.SetInsertPoint (wrapper_body);
2074 std::vector<llvm::Value *> raw_args (nargs);
2075 for (
size_t i = 0; i < nargs; ++i)
2078 arg =
builder.CreateConstInBoundsGEP1_32 (wrapper_arg, i);
2079 arg =
builder.CreateLoad (arg);
2086 llvm::Value *result = raw_fn.
call (
builder, raw_args);
2095 llvm::Value *zero =
builder.getInt32 (0);
2101 llvm::Function *llvm_function = wrapper.
to_llvm ();
2106 std::cout <<
"-------------------- optimized and wrapped ";
2107 std::cout <<
"--------------------\n";
2108 std::cout << *llvm_function << std::endl;
2109 llvm::verifyFunction (*llvm_function);
2112 llvm::ExecutionEngine* engine = tjit.
get_engine ();
2113 void *void_fn = engine->getPointerToFunction (llvm_function);
2123 std::cout <<
"jit fail: " << e.what () << std::endl;
2139 size_t nargs = ov_args.
length ();
2140 std::vector<octave_base_value *> args (nargs);
2141 for (
size_t i = 0; i < nargs; ++i)
2163 size_t nargs = ov_args.
length ();
2167 for (
size_t i = 0; i < nargs; ++i)
2176 : engine (tjit.get_engine ()), function (0), llvm_function (0)
2182 : engine (tjit.get_engine ()), function (0), llvm_function (0)
2199 std::vector<octave_base_value *> real_arguments (
arguments.size ());
2200 for (
size_t i = 0; i <
arguments.size (); ++i)
2207 real_arguments[i] = obv;
2211 function (&real_arguments[0]);
2213 for (
size_t i = 0; i <
arguments.size (); ++i)
2215 const std::string& name =
arguments[i].first;
2218 if (name.size () && name[0] !=
'#')
2233 for (
size_t i = 0; i <
bounds.size (); ++i)
2235 const std::string& arg_name =
bounds[i].second;
2240 if (type !=
bounds[i].first)
2262 std::cout <<
"-------------------- Compiling tree --------------------\n";
2264 blocks.
print (std::cout,
"octave jit ir");
2270 infer.get_blocks (),
2280 std::cout <<
"jit fail: " << e.what () << std::endl;
2288 std::cout <<
"-------------------- llvm ir --------------------";
2297 std::cout <<
"-------------------- optimized llvm ir "
2298 <<
"--------------------\n";
2310 vmap::const_iterator iter = extra_vars.find (vname);
2317 DEFUN (debug_jit, args, nargout,
2319 @deftypefn {Built-in Function} {@var{val} =} debug_jit ()\n\
2320 @deftypefnx {Built-in Function} {@var{old_val} =} debug_jit (@var{new_val})\n\
2321 @deftypefnx {Built-in Function} {} debug_jit (@var{new_val}, \"local\")\n\
2322 Query or set the internal variable that determines whether\n\
2323 debugging/tracing is enabled for Octave's JIT compiler.\n\
2325 When called from inside a function with the @qcode{\"local\"} option, the\n\
2326 variable is changed locally for the function and any subroutines it calls. \n\
2327 The original variable value is restored when exiting the function.\n\
2328 @seealso{jit_enable, jit_startcnt}\n\
2331 #if defined (HAVE_LLVM)
2334 warning (
"debug_jit: JIT compiling not available in this version of Octave");
2339 DEFUN (jit_enable, args, nargout,
2341 @deftypefn {Built-in Function} {@var{val} =} jit_enable ()\n\
2342 @deftypefnx {Built-in Function} {@var{old_val} =} jit_enable (@var{new_val})\n\
2343 @deftypefnx {Built-in Function} {} jit_enable (@var{new_val}, \"local\")\n\
2344 Query or set the internal variable that enables Octave's JIT compiler.\n\
2346 When called from inside a function with the @qcode{\"local\"} option, the\n\
2347 variable is changed locally for the function and any subroutines it calls. \n\
2348 The original variable value is restored when exiting the function.\n\
2349 @seealso{jit_startcnt, debug_jit}\n\
2352 #if defined (HAVE_LLVM)
2355 warning (
"jit_enable: JIT compiling not available in this version of Octave");
2360 DEFUN (jit_startcnt, args, nargout,
2362 @deftypefn {Built-in Function} {@var{val} =} jit_startcnt ()\n\
2363 @deftypefnx {Built-in Function} {@var{old_val} =} jit_startcnt (@var{new_val})\n\
2364 @deftypefnx {Built-in Function} {} jit_startcnt (@var{new_val}, \"local\")\n\
2365 Query or set the internal variable that determines whether JIT compilation\n\
2366 will take place for a specific loop. Because compilation is a costly\n\
2367 operation it does not make sense to employ JIT when the loop count is low.\n\
2368 By default only loops with greater than 1000 iterations will be accelerated.\n\
2370 When called from inside a function with the @qcode{\"local\"} option, the\n\
2371 variable is changed locally for the function and any subroutines it calls. \n\
2372 The original variable value is restored when exiting the function.\n\
2373 @seealso{jit_enable, debug_jit}\n\
2376 #if defined (HAVE_LLVM)
2380 warning (
"jit_enable: JIT compiling not available in this version of Octave");