25 #if ! defined (octave_jit_ir_h)
26 #define octave_jit_ir_h 1
28 #include "octave-config.h"
30 #if defined (HAVE_LLVM)
42 #define JIT_VISIT_IR_NOTEMPLATE \
45 JIT_METH(cond_branch); \
47 JIT_METH(extract_argument); \
48 JIT_METH(store_argument); \
52 JIT_METH(error_check); \
57 #define JIT_VISIT_IR_CONST \
58 JIT_METH(const_bool); \
59 JIT_METH(const_scalar); \
60 JIT_METH(const_complex); \
61 JIT_METH(const_index); \
62 JIT_METH(const_string); \
65 #define JIT_VISIT_IR_CLASSES \
66 JIT_VISIT_IR_NOTEMPLATE \
70 #define JIT_METH(cname) \
81 template <
typename T,
jit_type *(*EXTRACT_T)(void),
typename PASS_T = T,
110 const value_list&
constants (
void)
const {
return mconstants; }
112 template <
typename T>
120 #define DECL_ARG(n) const ARG ## n& arg ## n
122 #define JIT_CREATE(N) \
123 template <typename T, OCT_MAKE_DECL_LIST (typename, ARG, N)> \
124 T *create (OCT_MAKE_LIST (DECL_ARG, N)) \
126 T *ret = new T (OCT_MAKE_ARG_LIST (arg, N)); \
143 value_list all_values;
145 value_list mconstants;
161 iterator begin (
void) {
return mlist.begin (); }
163 const_iterator begin (
void)
const {
return mlist.begin (); }
165 iterator end (
void) {
return mlist.end (); }
167 const_iterator end (
void)
const {
return mlist.end (); }
169 iterator erase (iterator iter) {
return mlist.erase (iter); }
173 void insert_after (iterator iter,
jit_block *ablock);
177 void insert_before (iterator iter,
jit_block *ablock);
185 std::ostream& print_dom (std::ostream& os)
const;
189 std::list<jit_block *> mlist;
236 std::stringstream ss;
250 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const = 0;
253 {
return print (os); }
262 llvm::Value *
to_llvm (
void)
const
274 std::ostream&
print_indent (std::ostream& os,
size_t indent = 0)
const
276 for (
size_t i = 0;
i < indent * 8; ++
i)
299 jit_use (
void) : muser (0), mindex (0) { }
313 size_t index (
void)
const {
return mindex; }
319 std::list<jit_block *> user_parent_location (
void)
const;
324 PARENT_T::stash_value (avalue);
347 #define STASH_ARG(i) stash_argument (i, arg ## i);
349 #define JIT_INSTRUCTION_CTOR(N) \
350 jit_instruction (OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
351 : already_infered (N), marguments (N), mid (next_id ()), mparent (0) \
353 OCT_ITERATE_MACRO (STASH_ARG, N); \
362 #undef JIT_INSTRUCTION_CTOR
368 for (
size_t i = 0;
i < aarguments.size (); ++
i)
431 for (
size_t i = old; i < acount; ++
i)
450 virtual bool infer (
void) {
return false; }
454 virtual std::ostream&
short_print (std::ostream& os)
const;
458 std::list<jit_instruction *>::iterator
location (
void)
const
466 std::list<jit_instruction *>::iterator alocation)
472 size_t id (
void)
const {
return mid; }
480 static size_t next_id (
bool reset =
false)
482 static size_t ret = 0;
493 std::list<jit_instruction *>::iterator
mlocation;
497 #define JIT_VALUE_ACCEPT \
498 virtual void accept (jit_ir_walker& walker);
511 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
520 template <
typename T, jit_type *(*EXTRACT_T)(
void),
typename PASS_T,
bool QUOTE>
527 jit_const (PASS_T avalue) : mvalue (avalue)
532 PASS_T
value (
void)
const {
return mvalue; }
534 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
560 typedef instruction_list::iterator iterator;
561 typedef instruction_list::const_iterator const_iterator;
563 typedef std::set<jit_block *>
df_set;
566 static const size_t NO_ID =
static_cast<size_t> (-1);
569 : mvisit_count (avisit_count),
mid (NO_ID), idom (0), mname (aname),
575 void replace_in_phi (jit_block *ablock, jit_block *with);
585 void mark_alive (
void) {
malive =
true; }
588 jit_block *maybe_merge ();
591 void merge (jit_block& merge);
599 template <
typename T>
602 internal_append (instr);
617 return insert_after (loc->
location (), instr);
620 iterator
remove (iterator iter)
623 iter = instructions.erase (iter);
631 bool branch_alive (jit_block *asucc)
const;
637 iterator begin (
void) {
return instructions.begin (); }
639 const_iterator begin (
void)
const {
return instructions.begin (); }
641 iterator end (
void) {
return instructions.end (); }
643 const_iterator end (
void)
const {
return instructions.end (); }
645 iterator phi_begin (
void);
647 iterator phi_end (
void);
649 iterator nonphi_begin (
void);
652 size_t id (
void)
const {
return mid; }
655 const df_set& df (
void)
const {
return mdf; }
657 df_iterator df_begin (
void)
const {
return mdf.begin (); }
659 df_iterator df_end (
void)
const {
return mdf.end (); }
665 label (mvisit_count, number);
668 void label (
size_t avisit_count,
size_t&
number);
673 void compute_idom (jit_block& entry_block)
676 entry_block.
idom = &entry_block;
678 changed = update_idom (mvisit_count);
683 void compute_df (
void)
685 compute_df (mvisit_count);
688 void create_dom_tree (
void)
690 create_dom_tree (mvisit_count);
693 jit_block *dom_successor (
size_t idx)
const
695 return dom_succ[idx];
698 size_t dom_successor_count (
void)
const
700 return dom_succ.size ();
706 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
709 jit_block *asuccessor);
712 jit_block& asuccessor)
714 return maybe_split (factory, blocks, &asuccessor);
718 std::ostream& print_dom (std::ostream& os)
const;
720 virtual std::ostream&
short_print (std::ostream& os)
const
730 llvm::BasicBlock *
to_llvm (
void)
const;
732 std::list<jit_block *>::iterator
location (
void)
const
735 void stash_location (std::list<jit_block *>::iterator alocation)
739 size_t visit_count (
void)
const {
return mvisit_count; }
743 bool visited (
size_t avisit_count)
745 if (mvisit_count <= avisit_count)
747 mvisit_count = avisit_count + 1;
762 void compute_df (
size_t avisit_count);
764 bool update_idom (
size_t avisit_count);
766 void create_dom_tree (
size_t avisit_count);
768 static jit_block *idom_intersect (jit_block *i, jit_block *j);
774 std::vector<jit_block *> dom_succ;
776 instruction_list instructions;
797 stash_value (use.
value ());
802 jit_phi *user (
void)
const {
return muser; }
804 jit_block *user_parent (
void)
const;
820 bool has_top (
void)
const
822 return ! value_stack.
empty ();
827 return value_stack.top ();
832 value_stack.push (v);
862 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
870 std::stack<jit_value *> value_stack;
898 virtual std::ostream&
short_print (std::ostream& os)
const
903 dest ()->short_print (os);
904 return os <<
"#" <<
id ();
930 bool artificial (
void)
const {
return martificial; }
932 void mark_artificial (
void) { martificial =
true; }
934 virtual bool infer (
void)
946 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
951 os <<
" [artificial]";
968 mincomming.reserve (npred);
978 mincomming[mincomming.size () - 1].stash_value (from);
981 jit_block *incomming (
size_t i)
const
983 return mincomming[
i].value ();
986 llvm::BasicBlock *incomming_llvm (
size_t i)
const
988 return incomming (i)->to_llvm ();
993 virtual bool infer (
void);
995 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
997 std::stringstream ss;
1010 os << *incomming (i) <<
" -> ";
1020 llvm::PHINode *
to_llvm (
void)
const;
1024 std::vector<jit_phi_incomming> mincomming;
1032 #define JIT_TERMINATOR_CONST(N) \
1033 jit_terminator (size_t asuccessor_count, \
1034 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
1035 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), \
1036 malive (asuccessor_count, false) { }
1042 #undef JIT_TERMINATOR_CONST
1044 jit_block *
successor (
size_t idx = 0)
const
1046 return static_cast<jit_block *
> (
argument (idx));
1056 std::ostream&
print_successor (std::ostream& os,
size_t idx = 0)
const
1067 bool alive (
const jit_block *asuccessor)
const
1072 bool alive (
size_t idx)
const {
return malive[idx]; }
1074 bool alive (
int idx)
const {
return malive[idx]; }
1078 virtual bool infer (
void);
1080 llvm::TerminatorInst *
to_llvm (
void)
const;
1082 virtual bool check_alive (
size_t)
const {
return true; }
1084 std::vector<bool>
malive;
1095 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1113 std::ostream& print_cond (std::ostream& os)
const
1115 return cond ()->short_print (os);
1118 llvm::Value *cond_llvm (
void)
const
1120 return cond ()->to_llvm ();
1125 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1128 print_cond (os) <<
", ";
1141 : moperation (aoperation ())
1155 #define JIT_CALL_CONST(N) \
1156 jit_call (const jit_operation& aoperation, \
1157 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
1158 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation) { } \
1160 jit_call (const jit_operation& (*aoperation) (void), \
1161 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
1162 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation ()) \
1170 #undef JIT_CALL_CONST
1173 const std::vector<jit_value *>&
args)
1177 const jit_operation& operation (
void)
const {
return moperation; }
1179 bool can_error (
void)
const
1181 return overload ().can_error ();
1191 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1197 os <<
"call " << moperation.name () <<
" (";
1208 virtual bool infer (
void);
1233 :
jit_terminator (2, error, normal, acheck_for), mvariable (var) { }
1238 variable check_variable (
void)
const {
return mvariable; }
1240 bool has_check_for (
void)
const
1247 assert (has_check_for ());
1251 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
1257 if (! has_check_for ())
1259 return idx == 1 ?
true : check_for ()->can_error ();
1287 virtual bool infer (
void);
1291 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
1293 context resolve_context (
void)
const;
1295 virtual std::ostream&
short_print (std::ostream& os)
const
1297 return os <<
"magic_end" <<
"#" <<
id ();
1302 std::vector<context> contexts;
1317 return dest ()->name ();
1325 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1345 return dest->name ();
1360 return result ()->type ();
1363 llvm::Value *result_llvm (
void)
const
1365 return result ()->to_llvm ();
1368 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1372 dest->short_print (os);
1374 if (! isa<jit_variable> (res))
1404 return res ? res->
type () : 0;
1407 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1426 #define JIT_METH(clname) \
1427 virtual void visit (jit_ ## clname&) = 0;
1434 template <
typename T, jit_type *(*EXTRACT_T)(
void),
typename PASS_T,
bool QUOTE>
1438 walker.
visit (*
this);
1441 #undef JIT_VALUE_ACCEPT
jit_type * result(void) const
void stash_type(jit_type *new_ty)
void stash_parent(jit_block *aparent, std::list< jit_instruction * >::iterator alocation)
#define JIT_VISIT_IR_CLASSES
virtual std::ostream & short_print(std::ostream &os) const
virtual std::ostream & short_print(std::ostream &os) const
void stash_llvm(llvm::Value *compiled)
virtual void replace_with(jit_value *value)
jit_block * user_parent(void) const
std::list< jit_block * >::const_iterator const_iterator
const std::string & name(void) const
std::vector< jit_use > marguments
static jit_type * get_string(void)
llvm::Type * to_llvm(void) const
in that an updated permutation matrix is returned Note that if var
virtual void visit(jit_block &)=0
jit_block * parent(void) const
std::list< jit_instruction * >::iterator location(void) const
llvm::Type * type_llvm(void) const
#define JIT_CALL_CONST(N)
#define JIT_VISIT_IR_NOTEMPLATE
const std::string & type_name(void) const
virtual void accept(jit_ir_walker &walker)=0
jit_type * argument_type(size_t i) const
void error(const char *fmt,...)
jit_type * type(void) const
jit_block * first_use_block(void)
jit_const< octave_idx_type, jit_typeinfo::get_index > jit_const_index
std::list< jit_value * > value_list
llvm::TerminatorInst * to_llvm(void) const
virtual bool needs_release(void) const
bool has_llvm(void) const
is any Octave expression that can be evaluated in the code context that exists at the breakpoint When the breakpoint is and execution will stop if for example because it refers to an undefined variable
std::list< jit_instruction * >::iterator mlocation
void push_argument(jit_value *arg)
void stash_last_use(jit_instruction *alast_use)
void resize_arguments(size_t acount, jit_value *adefault=0)
llvm::Type * argument_type_llvm(size_t i) const
std::list< jit_instruction * > instruction_list
static const jit_operation & cast(jit_type *result)
bool alive(const jit_block *asuccessor) const
#define JIT_TERMINATOR_CONST(N)
virtual void accept(jit_ir_walker &walker)
jit_const< bool, jit_typeinfo::get_bool > jit_const_bool
static llvm::LLVMContext & context
virtual void construct_ssa(void)
std::vector< bool > malive
returns the type of the matrix and caches it for future use Called with more than one argument
llvm::BasicBlock * parent_llvm(void) const
jit_block * successor(size_t idx=0) const
bool in_worklist(void) const
std::string print_string(void)
size_t argument_count(void) const
the sparsity preserving column transformation such that that defines the pivoting threshold can be given in which case it defines the c
jit_const< double, jit_typeinfo::get_scalar > jit_const_scalar
void stash_argument(size_t i, jit_value *arg)
virtual void pop_variable(void)
With real return the complex result
void stash_in_worklist(bool ain_worklist)
llvm::BasicBlock * to_llvm(void) const
std::ostream & print_indent(std::ostream &os, size_t indent=0) const
size_t successor_index(const jit_block *asuccessor) const
df_set::const_iterator df_iterator
LIST_T * value(void) const
std::ostream & jit_print(std::ostream &os, jit_value *avalue)
jit_const< jit_range, jit_typeinfo::get_range, const jit_range & > jit_const_range
if they have changed since they were last compiled
size_t use_count(void) const
std::vector< jit_type * > already_infered
jit_use * first_use(void) const
const std::vector< jit_type * > & argument_types(void) const
std::set< jit_block * > df_set
=val(i)}if ode{val(i)}occurs in table i
size_t successor_count(void) const
jit_const< Complex, jit_typeinfo::get_complex > jit_const_complex
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!
#define JIT_INSTRUCTION_CTOR(N)
jit_instruction * last_use(void) const
static size_t next_id(bool reset=false)
const value_list & constants(void) const
jit_instruction * mlast_use
llvm::Value * argument_llvm(size_t i) const
std::list< jit_block * >::iterator iterator
static void reset_ids(void)
jit_instruction * front(void)
jit_const< std::string, jit_typeinfo::get_string, const std::string &, true > jit_const_string
static jit_type * get_any(void)
jit_instruction * back(void)
virtual bool check_alive(size_t) const
virtual void push_variable(void)
std::ostream & print_successor(std::ostream &os, size_t idx=0) const
virtual std::ostream & short_print(std::ostream &os) const
NODE_T * next(void) const
jit_instruction * user(void) const
llvm::BasicBlock * successor_llvm(size_t idx=0) const
std::ostream & print_argument(std::ostream &os, size_t i) const
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
void do_construct_ssa(size_t start, size_t end)
std::ostream & operator<<(std::ostream &os, const jit_block_list &blocks)
virtual std::ostream & print(std::ostream &os, size_t indent=0) const =0