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)); \
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;
229 std::stringstream ss;
243 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const = 0;
246 {
return print (os); }
269 for (
size_t i = 0; i < indent * 8; ++i)
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; }
474 static size_t ret = 0;
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>
524 PASS_T
value (
void)
const {
return mvalue; }
526 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
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);
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);
602 return insert_before (loc->
location (), 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;
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)
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);
789 stash_value (use.
value ());
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
895 dest ()->short_print (os);
896 return os <<
"#" <<
id ();
938 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
943 os <<
" [artificial]";
960 mincomming.reserve (npred);
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) <<
" -> ";
1005 if (i + 1 < argument_count ())
1012 llvm::PHINode *
to_llvm (
void)
const;
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
1037 return static_cast<jit_block *
> (
argument (idx));
1058 bool alive (
const jit_block *asuccessor)
const
1069 virtual bool infer (
void);
1071 llvm::TerminatorInst *
to_llvm (
void)
const;
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)
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 () <<
" (";
1193 if (i + 1 < argument_count ())
1199 virtual bool infer (
void);
1220 static std::string variable_to_string (variable v);
1224 :
jit_terminator (2, error, normal, acheck_for), mvariable (var) { }
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 ();
1278 virtual bool infer (
void);
1282 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const;
1284 context resolve_context (
void)
const;
1288 return os <<
"magic_end" <<
"#" <<
id ();
1306 const std::string& name (
void)
const
1308 return dest ()->name ();
1316 virtual std::ostream&
print (std::ostream& os,
size_t indent = 0)
const
1320 return short_print (os) <<
" = extract " << name ();
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