25 #if !defined (octave_jit_ir_h)
26 #define octave_jit_ir_h 1
40 #define JIT_VISIT_IR_NOTEMPLATE \
43 JIT_METH(cond_branch); \
45 JIT_METH(extract_argument); \
46 JIT_METH(store_argument); \
50 JIT_METH(error_check); \
55 #define JIT_VISIT_IR_CONST \
56 JIT_METH(const_bool); \
57 JIT_METH(const_scalar); \
58 JIT_METH(const_complex); \
59 JIT_METH(const_index); \
60 JIT_METH(const_string); \
63 #define JIT_VISIT_IR_CLASSES \
64 JIT_VISIT_IR_NOTEMPLATE \
68 #define JIT_METH(cname) \
79 template <
typename T,
jit_type *(*EXTRACT_T)(void),
typename PASS_T = T,
106 const value_list&
constants (
void)
const {
return mconstants; }
108 template <
typename T>
116 #define DECL_ARG(n) const ARG ## n& arg ## n
117 #define JIT_CREATE(N) \
118 template <typename T, OCT_MAKE_DECL_LIST (typename, ARG, N)> \
119 T *create (OCT_MAKE_LIST (DECL_ARG, N)) \
121 T *ret = new T (OCT_MAKE_ARG_LIST (arg, N)); \
136 value_list all_values;
138 value_list mconstants;
154 iterator begin (
void) {
return mlist.begin (); }
156 const_iterator begin (
void)
const {
return mlist.begin (); }
158 iterator end (
void) {
return mlist.end (); }
160 const_iterator end (
void)
const {
return mlist.end (); }
162 iterator erase (iterator iter) {
return mlist.erase (iter); }
166 void insert_after (iterator iter,
jit_block *ablock);
170 void insert_before (iterator iter,
jit_block *ablock);
176 std::ostream&
print (std::ostream& os,
const std::string& header)
const;
178 std::ostream& print_dom (std::ostream& os)
const;
182 std::list<jit_block *> mlist;
229 std::stringstream ss;
243 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const = 0;
246 {
return print (os); }
255 llvm::Value *
to_llvm (
void)
const
267 std::ostream&
print_indent (std::ostream& os,
size_t indent = 0)
const
269 for (
size_t i = 0; i < indent * 8; ++i)
292 jit_use (
void) : muser (0), mindex (0) { }
306 size_t index (
void)
const {
return mindex; }
312 std::list<jit_block *> user_parent_location (
void)
const;
317 PARENT_T::stash_value (avalue);
340 #define STASH_ARG(i) stash_argument (i, arg ## i);
341 #define JIT_INSTRUCTION_CTOR(N) \
342 jit_instruction (OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
343 : already_infered (N), marguments (N), mid (next_id ()), mparent (0) \
345 OCT_ITERATE_MACRO (STASH_ARG, N); \
354 #undef JIT_INSTRUCTION_CTOR
360 for (
size_t i = 0; i < aarguments.size (); ++i)
423 for (
size_t i = old; i < acount; ++i)
442 virtual bool infer (
void) {
return false; }
446 virtual std::ostream&
short_print (std::ostream& os)
const;
450 std::list<jit_instruction *>::iterator
location (
void)
const
458 std::list<jit_instruction *>::iterator alocation)
464 size_t id (
void)
const {
return mid; }
472 static size_t next_id (
bool reset =
false)
474 static size_t ret = 0;
485 std::list<jit_instruction *>::iterator
mlocation;
489 #define JIT_VALUE_ACCEPT \
490 virtual void accept (jit_ir_walker& walker);
503 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
512 template <
typename T, jit_type *(*EXTRACT_T)(
void),
typename PASS_T,
bool QUOTE>
519 jit_const (PASS_T avalue) : mvalue (avalue)
524 PASS_T value (
void)
const {
return mvalue; }
526 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
552 typedef instruction_list::iterator iterator;
553 typedef instruction_list::const_iterator const_iterator;
555 typedef std::set<jit_block *>
df_set;
558 static const size_t NO_ID =
static_cast<size_t> (-1);
560 jit_block (
const std::string& aname,
size_t avisit_count = 0)
561 : mvisit_count (avisit_count),
mid (NO_ID), idom (0), mname (aname),
567 void replace_in_phi (jit_block *ablock, jit_block *with);
577 void mark_alive (
void) {
malive =
true; }
580 jit_block *maybe_merge ();
583 void merge (jit_block& merge);
585 const std::string& name (
void)
const {
return mname; }
591 template <
typename T>
594 internal_append (instr);
609 return insert_after (loc->
location (), instr);
612 iterator
remove (iterator iter)
615 iter = instructions.erase (iter);
623 bool branch_alive (jit_block *asucc)
const;
629 iterator begin (
void) {
return instructions.begin (); }
631 const_iterator begin (
void)
const {
return instructions.begin (); }
633 iterator end (
void) {
return instructions.end (); }
635 const_iterator end (
void)
const {
return instructions.end (); }
637 iterator phi_begin (
void);
639 iterator phi_end (
void);
641 iterator nonphi_begin (
void);
644 size_t id (
void)
const {
return mid; }
647 const df_set& df (
void)
const {
return mdf; }
649 df_iterator df_begin (
void)
const {
return mdf.begin (); }
651 df_iterator df_end (
void)
const {
return mdf.end (); }
657 label (mvisit_count, number);
660 void label (
size_t avisit_count,
size_t& number);
665 void compute_idom (jit_block& entry_block)
668 entry_block.
idom = &entry_block;
670 changed = update_idom (mvisit_count);
675 void compute_df (
void)
677 compute_df (mvisit_count);
680 void create_dom_tree (
void)
682 create_dom_tree (mvisit_count);
685 jit_block *dom_successor (
size_t idx)
const
687 return dom_succ[idx];
690 size_t dom_successor_count (
void)
const
692 return dom_succ.size ();
698 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
701 jit_block *asuccessor);
704 jit_block& asuccessor)
706 return maybe_split (factory, blocks, &asuccessor);
710 std::ostream& print_dom (std::ostream& os)
const;
712 virtual std::ostream&
short_print (std::ostream& os)
const
722 llvm::BasicBlock *
to_llvm (
void)
const;
724 std::list<jit_block *>::iterator
location (
void)
const
727 void stash_location (std::list<jit_block *>::iterator alocation)
731 size_t visit_count (
void)
const {
return mvisit_count; }
735 bool visited (
size_t avisit_count)
737 if (mvisit_count <= avisit_count)
739 mvisit_count = avisit_count + 1;
754 void compute_df (
size_t avisit_count);
756 bool update_idom (
size_t avisit_count);
758 void create_dom_tree (
size_t avisit_count);
760 static jit_block *idom_intersect (jit_block *i, jit_block *j);
766 std::vector<jit_block *> dom_succ;
768 instruction_list instructions;
789 stash_value (use.
value ());
794 jit_phi *user (
void)
const {
return muser; }
796 jit_block *user_parent (
void)
const;
808 const std::string &name (
void)
const {
return mname; }
812 bool has_top (
void)
const
814 return ! value_stack.empty ();
819 return value_stack.top ();
824 value_stack.push (v);
854 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
862 std::stack<jit_value *> value_stack;
890 virtual std::ostream&
short_print (std::ostream& os)
const
895 dest ()->short_print (os);
896 return os <<
"#" <<
id ();
922 bool artificial (
void)
const {
return martificial; }
924 void mark_artificial (
void) { martificial =
true; }
926 virtual bool infer (
void)
938 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
943 os <<
" [artificial]";
960 mincomming.reserve (npred);
966 void add_incomming (jit_block *from,
jit_value *value)
970 mincomming[mincomming.size () - 1].stash_value (from);
973 jit_block *incomming (
size_t i)
const
975 return mincomming[i].value ();
978 llvm::BasicBlock *incomming_llvm (
size_t i)
const
980 return incomming (i)->to_llvm ();
985 virtual bool infer (
void);
987 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
989 std::stringstream ss;
992 std::string ss_str = ss.str ();
993 std::string indent_str (ss_str.size (),
' ');
1002 os << *incomming (i) <<
" -> ";
1012 llvm::PHINode *
to_llvm (
void)
const;
1016 std::vector<jit_phi_incomming> mincomming;
1023 #define JIT_TERMINATOR_CONST(N) \
1024 jit_terminator (size_t asuccessor_count, \
1025 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
1026 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), \
1027 malive (asuccessor_count, false) { }
1033 #undef JIT_TERMINATOR_CONST
1035 jit_block *
successor (
size_t idx = 0)
const
1037 return static_cast<jit_block *
> (
argument (idx));
1047 std::ostream&
print_successor (std::ostream& os,
size_t idx = 0)
const
1058 bool alive (
const jit_block *asuccessor)
const
1063 bool alive (
size_t idx)
const {
return malive[idx]; }
1065 bool alive (
int idx)
const {
return malive[idx]; }
1069 virtual bool infer (
void);
1071 llvm::TerminatorInst *
to_llvm (
void)
const;
1073 virtual bool check_alive (
size_t)
const {
return true; }
1075 std::vector<bool>
malive;
1086 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1104 std::ostream& print_cond (std::ostream& os)
const
1106 return cond ()->short_print (os);
1109 llvm::Value *cond_llvm (
void)
const
1111 return cond ()->to_llvm ();
1116 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1119 print_cond (os) <<
", ";
1132 : moperation (aoperation ())
1146 #define JIT_CALL_CONST(N) \
1147 jit_call (const jit_operation& aoperation, \
1148 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
1149 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation) { } \
1151 jit_call (const jit_operation& (*aoperation) (void), \
1152 OCT_MAKE_DECL_LIST (jit_value *, arg, N)) \
1153 : jit_instruction (OCT_MAKE_ARG_LIST (arg, N)), moperation (aoperation ()) \
1161 #undef JIT_CALL_CONST
1164 const std::vector<jit_value *>& args)
1168 const jit_operation& operation (
void)
const {
return moperation; }
1170 bool can_error (
void)
const
1172 return overload ().can_error ();
1182 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1188 os <<
"call " << moperation.name () <<
" (";
1199 virtual bool infer (
void);
1220 static std::string variable_to_string (variable v);
1224 :
jit_terminator (2, error, normal, acheck_for), mvariable (var) { }
1229 variable check_variable (
void)
const {
return mvariable; }
1231 bool has_check_for (
void)
const
1238 assert (has_check_for ());
1242 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
1248 if (! has_check_for ())
1250 return idx == 1 ?
true : check_for ()->can_error ();
1265 context (
void) : value (0), index (0), count (0)
1278 virtual bool infer (
void);
1282 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
1284 context resolve_context (
void)
const;
1286 virtual std::ostream&
short_print (std::ostream& os)
const
1288 return os <<
"magic_end" <<
"#" <<
id ();
1293 std::vector<context> contexts;
1306 const std::string& name (
void)
const
1308 return dest ()->name ();
1316 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1334 const std::string& name (
void)
const
1336 return dest->name ();
1351 return result ()->type ();
1354 llvm::Value *result_llvm (
void)
const
1359 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1363 dest->short_print (os);
1365 if (! isa<jit_variable> (res))
1395 return res ? res->
type () : 0;
1398 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1403 os <<
" " << *result ();
1417 #define JIT_METH(clname) \
1418 virtual void visit (jit_ ## clname&) = 0;
1425 template <
typename T, jit_type *(*EXTRACT_T)(
void),
typename PASS_T,
bool QUOTE>
1429 walker.
visit (*
this);
1432 #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
virtual void visit(jit_block &)=0
jit_block * parent(void) const
llvm::Value * to_llvm(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
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
llvm::BasicBlock * parent_llvm(void) const
jit_block * successor(size_t idx=0) const
bool in_worklist(void) const
std::string print_string(void)
jit_value * argument(size_t i) const
size_t size(T const (&)[z])
size_t argument_count(void) const
jit_const< double, jit_typeinfo::get_scalar > jit_const_scalar
void stash_argument(size_t i, jit_value *arg)
virtual void pop_variable(void)
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
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
size_t successor_count(void) const
jit_const< Complex, jit_typeinfo::get_complex > jit_const_complex
#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
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
const std::vector< jit_use > & arguments(void) const