Mercurial > hg > octave-nkf
comparison src/pt-jit.h @ 14935:5801e031a3b5
Place releases after last use and generalize dom visiting
author | Max Brister <max@2bass.com> |
---|---|
date | Mon, 04 Jun 2012 13:10:44 -0500 |
parents | 1f914446157d |
children | 32deb562ae77 |
comparison
equal
deleted
inserted
replaced
14934:4ec5f49cdfe4 | 14935:5801e031a3b5 |
---|---|
161 // and code generation. | 161 // and code generation. |
162 class | 162 class |
163 jit_function | 163 jit_function |
164 { | 164 { |
165 public: | 165 public: |
166 struct overload | 166 struct |
167 overload | |
167 { | 168 { |
168 overload (void) : function (0), can_error (true), result (0) {} | 169 overload (void) : function (0), can_error (true), result (0) {} |
169 | 170 |
170 overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0) : | 171 overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0) : |
171 function (f), can_error (e), result (r), arguments (1) | 172 function (f), can_error (e), side_effects (s), result (r), arguments (1) |
172 { | 173 { |
173 arguments[0] = arg0; | 174 arguments[0] = arg0; |
174 } | 175 } |
175 | 176 |
176 overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, | 177 overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0, |
177 jit_type *arg1) : function (f), can_error (e), result (r), | 178 jit_type *arg1) : function (f), can_error (e), side_effects (s), |
178 arguments (2) | 179 result (r), arguments (2) |
179 { | 180 { |
180 arguments[0] = arg0; | 181 arguments[0] = arg0; |
181 arguments[1] = arg1; | 182 arguments[1] = arg1; |
182 } | 183 } |
183 | 184 |
184 llvm::Function *function; | 185 llvm::Function *function; |
185 bool can_error; | 186 bool can_error; |
187 bool side_effects; | |
186 jit_type *result; | 188 jit_type *result; |
187 std::vector<jit_type*> arguments; | 189 std::vector<jit_type*> arguments; |
188 }; | 190 }; |
189 | 191 |
190 void add_overload (const overload& func) | 192 void add_overload (const overload& func) |
191 { | 193 { |
192 add_overload (func, func.arguments); | 194 add_overload (func, func.arguments); |
193 } | 195 } |
194 | 196 |
195 void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0) | 197 void add_overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0) |
196 { | 198 { |
197 overload ol (f, e, r, arg0); | 199 overload ol (f, e, s, r, arg0); |
198 add_overload (ol); | 200 add_overload (ol); |
199 } | 201 } |
200 | 202 |
201 void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, | 203 void add_overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0, |
202 jit_type *arg1) | 204 jit_type *arg1) |
203 { | 205 { |
204 overload ol (f, e, r, arg0, arg1); | 206 overload ol (f, e, s, r, arg0, arg1); |
205 add_overload (ol); | 207 add_overload (ol); |
206 } | 208 } |
207 | 209 |
208 void add_overload (const overload& func, | 210 void add_overload (const overload& func, |
209 const std::vector<jit_type*>& args); | 211 const std::vector<jit_type*>& args); |
289 static const jit_function& grab (void) { return instance->grab_fn; } | 291 static const jit_function& grab (void) { return instance->grab_fn; } |
290 | 292 |
291 static const jit_function& release (void) | 293 static const jit_function& release (void) |
292 { | 294 { |
293 return instance->release_fn; | 295 return instance->release_fn; |
296 } | |
297 | |
298 static const jit_function::overload& get_release (jit_type *type) | |
299 { | |
300 return instance->release_fn.get_overload (type); | |
294 } | 301 } |
295 | 302 |
296 static const jit_function& print_value (void) | 303 static const jit_function& print_value (void) |
297 { | 304 { |
298 return instance->print_fn; | 305 return instance->print_fn; |
488 // The low level octave jit ir | 495 // The low level octave jit ir |
489 // this ir is close to llvm, but contains information for doing type inference. | 496 // this ir is close to llvm, but contains information for doing type inference. |
490 // We convert the octave parse tree to this IR directly. | 497 // We convert the octave parse tree to this IR directly. |
491 | 498 |
492 #define JIT_VISIT_IR_NOTEMPLATE \ | 499 #define JIT_VISIT_IR_NOTEMPLATE \ |
493 JIT_METH(block); \ | 500 JIT_METH(block) \ |
494 JIT_METH(break); \ | 501 JIT_METH(break) \ |
495 JIT_METH(cond_break); \ | 502 JIT_METH(cond_break) \ |
496 JIT_METH(call); \ | 503 JIT_METH(call) \ |
497 JIT_METH(extract_argument); \ | 504 JIT_METH(extract_argument) \ |
498 JIT_METH(store_argument); \ | 505 JIT_METH(store_argument) \ |
499 JIT_METH(phi); \ | 506 JIT_METH(phi) \ |
500 JIT_METH(variable) | 507 JIT_METH(variable) |
501 | 508 |
509 #define JIT_VISIT_IR_CONST \ | |
510 JIT_METH(const_scalar) \ | |
511 JIT_METH(const_index) \ | |
512 JIT_METH(const_string) \ | |
513 JIT_METH(const_range) | |
514 | |
515 #define JIT_VISIT_IR_ABSTRACT \ | |
516 JIT_METH(instruction) \ | |
517 JIT_METH(terminator) | |
518 | |
502 #define JIT_VISIT_IR_CLASSES \ | 519 #define JIT_VISIT_IR_CLASSES \ |
503 JIT_VISIT_IR_NOTEMPLATE; \ | 520 JIT_VISIT_IR_NOTEMPLATE \ |
504 JIT_VISIT_IR_CONST | 521 JIT_VISIT_IR_CONST |
505 | 522 |
523 #define JIT_VISIT_IR_ALL \ | |
524 JIT_VISIT_IR_CLASSES \ | |
525 JIT_VISIT_IR_ABSTRACT | |
526 | |
527 // forward declare all ir classes | |
528 #define JIT_METH(cname) \ | |
529 class jit_ ## cname; | |
530 | |
531 JIT_VISIT_IR_ABSTRACT | |
532 JIT_VISIT_IR_NOTEMPLATE | |
533 | |
534 #undef JIT_METH | |
535 | |
536 // constants are typedefs from jit_const | |
537 template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T = T, | |
538 bool QUOTE=false> | |
539 class jit_const; | |
540 | |
541 typedef jit_const<double, jit_typeinfo::get_scalar> jit_const_scalar; | |
542 typedef jit_const<octave_idx_type, jit_typeinfo::get_index> jit_const_index; | |
543 | |
544 typedef jit_const<std::string, jit_typeinfo::get_string, const std::string&, true> | |
545 jit_const_string; | |
546 typedef jit_const<jit_range, jit_typeinfo::get_range, const jit_range&> | |
547 jit_const_range; | |
506 | 548 |
507 class jit_ir_walker; | 549 class jit_ir_walker; |
508 class jit_use; | 550 class jit_use; |
509 | 551 |
510 class | 552 class |
564 | 606 |
565 void stash_llvm (llvm::Value *compiled) | 607 void stash_llvm (llvm::Value *compiled) |
566 { | 608 { |
567 llvm_value = compiled; | 609 llvm_value = compiled; |
568 } | 610 } |
611 | |
612 #define JIT_METH(cname) \ | |
613 virtual bool is_ ## cname (void) const \ | |
614 { return false; } \ | |
615 \ | |
616 virtual jit_ ## cname *to_ ## cname (void) \ | |
617 { return 0; } \ | |
618 \ | |
619 virtual const jit_ ## cname *to_ ## cname (void) const \ | |
620 { return 0; } | |
621 | |
622 JIT_VISIT_IR_NOTEMPLATE | |
623 JIT_VISIT_IR_ABSTRACT | |
624 | |
625 #undef JIT_METH | |
626 | |
569 protected: | 627 protected: |
570 std::ostream& print_indent (std::ostream& os, size_t indent) const | 628 std::ostream& print_indent (std::ostream& os, size_t indent) const |
571 { | 629 { |
572 for (size_t i = 0; i < indent * 8; ++i) | 630 for (size_t i = 0; i < indent * 8; ++i) |
573 os << " "; | 631 os << " "; |
581 size_t myuse_count; | 639 size_t myuse_count; |
582 }; | 640 }; |
583 | 641 |
584 std::ostream& operator<< (std::ostream& os, const jit_value& value); | 642 std::ostream& operator<< (std::ostream& os, const jit_value& value); |
585 | 643 |
586 class jit_instruction; | 644 #define JIT_GEN_CASTS(cname) \ |
587 class jit_block; | 645 virtual bool is_ ## cname (void) const \ |
646 { return true; } \ | |
647 \ | |
648 virtual jit_ ## cname *to_ ## cname (void) \ | |
649 { return this; } \ | |
650 \ | |
651 virtual const jit_ ## cname *to_ ## cname (void) const \ | |
652 { return this; } | |
588 | 653 |
589 class | 654 class |
590 jit_use | 655 jit_use |
591 { | 656 { |
592 public: | 657 public: |
612 size_t index (void) const { return mindex; } | 677 size_t index (void) const { return mindex; } |
613 | 678 |
614 jit_instruction *user (void) const { return muser; } | 679 jit_instruction *user (void) const { return muser; } |
615 | 680 |
616 jit_block *user_parent (void) const; | 681 jit_block *user_parent (void) const; |
682 | |
683 std::list<jit_block *> user_parent_location (void) const; | |
617 | 684 |
618 void stash_value (jit_value *avalue, jit_instruction *auser = 0, | 685 void stash_value (jit_value *avalue, jit_instruction *auser = 0, |
619 size_t aindex = -1) | 686 size_t aindex = -1) |
620 { | 687 { |
621 remove (); | 688 remove (); |
666 jit_use *mprev; | 733 jit_use *mprev; |
667 jit_instruction *muser; | 734 jit_instruction *muser; |
668 size_t mindex; | 735 size_t mindex; |
669 }; | 736 }; |
670 | 737 |
671 class jit_variable; | |
672 | |
673 class | 738 class |
674 jit_instruction : public jit_value | 739 jit_instruction : public jit_value |
675 { | 740 { |
676 public: | 741 public: |
677 // FIXME: this code could be so much pretier with varadic templates... | 742 // FIXME: this code could be so much pretier with varadic templates... |
735 llvm::Type *argument_type_llvm (size_t i) const | 800 llvm::Type *argument_type_llvm (size_t i) const |
736 { | 801 { |
737 assert (argument (i)); | 802 assert (argument (i)); |
738 return argument_type (i)->to_llvm (); | 803 return argument_type (i)->to_llvm (); |
739 } | 804 } |
805 | |
806 // generate functions of form argument_type where type is any subclass of | |
807 // jit_value | |
808 #define JIT_METH(cname) \ | |
809 jit_ ## cname *argument_ ## cname (size_t i) const \ | |
810 { \ | |
811 jit_value *arg = argument (i); \ | |
812 return arg ? arg->to_ ## cname () : 0; \ | |
813 } | |
814 | |
815 JIT_VISIT_IR_ABSTRACT | |
816 JIT_VISIT_IR_NOTEMPLATE | |
817 | |
818 #undef JIT_METH | |
740 | 819 |
741 std::ostream& print_argument (std::ostream& os, size_t i) const | 820 std::ostream& print_argument (std::ostream& os, size_t i) const |
742 { | 821 { |
743 if (argument (i)) | 822 if (argument (i)) |
744 return argument (i)->short_print (os); | 823 return argument (i)->short_print (os); |
768 | 847 |
769 // argument types which have been infered already | 848 // argument types which have been infered already |
770 const std::vector<jit_type *>& argument_types (void) const | 849 const std::vector<jit_type *>& argument_types (void) const |
771 { return already_infered; } | 850 { return already_infered; } |
772 | 851 |
852 virtual bool dead (void) const { return false; } | |
853 | |
854 virtual bool almost_dead (void) const { return false; } | |
855 | |
773 virtual bool infer (void) { return false; } | 856 virtual bool infer (void) { return false; } |
774 | 857 |
858 void remove (void); | |
859 | |
775 void push_variable (void); | 860 void push_variable (void); |
776 | 861 |
777 void pop_variable (void); | 862 void pop_variable (void); |
778 | 863 |
779 virtual std::ostream& short_print (std::ostream& os) const; | 864 virtual std::ostream& short_print (std::ostream& os) const; |
780 | 865 |
781 jit_block *parent (void) const { return mparent; } | 866 jit_block *parent (void) const { return mparent; } |
782 | 867 |
868 std::list<jit_instruction *>::iterator location (void) const | |
869 { | |
870 return mlocation; | |
871 } | |
872 | |
783 llvm::BasicBlock *parent_llvm (void) const; | 873 llvm::BasicBlock *parent_llvm (void) const; |
784 | 874 |
785 void stash_parent (jit_block *aparent) | 875 void stash_parent (jit_block *aparent, |
786 { | 876 std::list<jit_instruction *>::iterator alocation) |
787 assert (! mparent); | 877 { |
788 mparent = aparent; | 878 mparent = aparent; |
879 mlocation = alocation; | |
789 } | 880 } |
790 | 881 |
791 jit_variable *tag (void) const; | 882 jit_variable *tag (void) const; |
792 | 883 |
793 void stash_tag (jit_variable *atag); | 884 void stash_tag (jit_variable *atag); |
885 | |
886 JIT_GEN_CASTS (instruction) | |
794 protected: | 887 protected: |
795 std::vector<jit_type *> already_infered; | 888 std::vector<jit_type *> already_infered; |
796 private: | 889 private: |
797 static size_t next_id (bool reset = false) | 890 static size_t next_id (bool reset = false) |
798 { | 891 { |
807 | 900 |
808 jit_use mtag; | 901 jit_use mtag; |
809 | 902 |
810 size_t id; | 903 size_t id; |
811 jit_block *mparent; | 904 jit_block *mparent; |
905 std::list<jit_instruction *>::iterator mlocation; | |
812 }; | 906 }; |
813 | 907 |
814 // defnie accept methods for subclasses | 908 // defnie accept methods for subclasses |
815 #define JIT_VALUE_ACCEPT(clname) \ | 909 #define JIT_VALUE_ACCEPT(clname) \ |
816 virtual void accept (jit_ir_walker& walker); | 910 virtual void accept (jit_ir_walker& walker); |
817 | 911 |
818 template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T = T, | 912 template <typename T, jit_type *(*EXTRACT_T)(void), typename PASS_T, |
819 bool QUOTE=false> | 913 bool QUOTE> |
820 class | 914 class |
821 jit_const : public jit_instruction | 915 jit_const : public jit_instruction |
822 { | 916 { |
823 public: | 917 public: |
824 typedef PASS_T pass_t; | 918 typedef PASS_T pass_t; |
845 JIT_VALUE_ACCEPT (jit_const); | 939 JIT_VALUE_ACCEPT (jit_const); |
846 private: | 940 private: |
847 T mvalue; | 941 T mvalue; |
848 }; | 942 }; |
849 | 943 |
850 typedef jit_const<double, jit_typeinfo::get_scalar> jit_const_scalar; | |
851 typedef jit_const<octave_idx_type, jit_typeinfo::get_index> jit_const_index; | |
852 | |
853 typedef jit_const<std::string, jit_typeinfo::get_string, const std::string&, true> | |
854 jit_const_string; | |
855 typedef jit_const<jit_range, jit_typeinfo::get_range, const jit_range&> | |
856 jit_const_range; | |
857 | |
858 #define JIT_VISIT_IR_CONST \ | |
859 JIT_METH(const_scalar); \ | |
860 JIT_METH(const_index); \ | |
861 JIT_METH(const_string); \ | |
862 JIT_METH(const_range) | |
863 | |
864 class jit_terminator; | |
865 class jit_phi; | |
866 class jit_convert; | |
867 | |
868 class | 944 class |
869 jit_block : public jit_value | 945 jit_block : public jit_value |
870 { | 946 { |
871 public: | 947 public: |
872 typedef std::list<jit_instruction *> instruction_list; | 948 typedef std::list<jit_instruction *> instruction_list; |
882 | 958 |
883 const std::string& name (void) const { return mname; } | 959 const std::string& name (void) const { return mname; } |
884 | 960 |
885 jit_instruction *prepend (jit_instruction *instr); | 961 jit_instruction *prepend (jit_instruction *instr); |
886 | 962 |
963 jit_instruction *prepend_after_phi (jit_instruction *instr); | |
964 | |
887 jit_instruction *append (jit_instruction *instr); | 965 jit_instruction *append (jit_instruction *instr); |
888 | 966 |
889 jit_instruction *insert_before (iterator loc, jit_instruction *instr); | 967 jit_instruction *insert_before (iterator loc, jit_instruction *instr); |
890 | 968 |
891 jit_instruction *insert_after (iterator loc, jit_instruction *instr); | 969 jit_instruction *insert_after (iterator loc, jit_instruction *instr); |
892 | 970 |
893 void remove (jit_block::iterator iter) | 971 void remove (jit_block::iterator iter) |
894 { | 972 { |
973 jit_instruction *instr = *iter; | |
895 instructions.erase (iter); | 974 instructions.erase (iter); |
975 instr->stash_parent (0, instructions.end ()); | |
896 } | 976 } |
897 | 977 |
898 jit_terminator *terminator (void) const; | 978 jit_terminator *terminator (void) const; |
899 | 979 |
900 jit_block *pred (size_t idx) const; | 980 jit_block *pred (size_t idx) const; |
999 void create_dom_tree (void) | 1079 void create_dom_tree (void) |
1000 { | 1080 { |
1001 create_dom_tree (mvisit_count); | 1081 create_dom_tree (mvisit_count); |
1002 } | 1082 } |
1003 | 1083 |
1004 void construct_ssa (jit_convert& convert) | 1084 // visit blocks in the order of the dominator tree |
1005 { | 1085 // inorder - Run on the root first, then children |
1006 do_construct_ssa (convert, mvisit_count); | 1086 // postorder - Run on children first, then the root |
1007 } | 1087 template <typename func_type0, typename func_type1> |
1088 void visit_dom (func_type0 inorder, func_type1 postorder) | |
1089 { | |
1090 do_visit_dom (mvisit_count, inorder, postorder); | |
1091 } | |
1092 | |
1093 // call pop_varaible on all instructions | |
1094 void pop_all (void); | |
1008 | 1095 |
1009 virtual std::ostream& print (std::ostream& os, size_t indent) const | 1096 virtual std::ostream& print (std::ostream& os, size_t indent) const |
1010 { | 1097 { |
1011 print_indent (os, indent) << mname << ": %pred = "; | 1098 print_indent (os, indent) << mname << ": %pred = "; |
1012 for (size_t i = 0; i < pred_count (); ++i) | 1099 for (size_t i = 0; i < pred_count (); ++i) |
1034 } | 1121 } |
1035 | 1122 |
1036 llvm::BasicBlock *to_llvm (void) const; | 1123 llvm::BasicBlock *to_llvm (void) const; |
1037 | 1124 |
1038 JIT_VALUE_ACCEPT (block) | 1125 JIT_VALUE_ACCEPT (block) |
1126 JIT_GEN_CASTS (block) | |
1039 private: | 1127 private: |
1040 void compute_df (size_t visit_count); | 1128 void compute_df (size_t visit_count); |
1041 | 1129 |
1042 bool update_idom (size_t visit_count); | 1130 bool update_idom (size_t visit_count); |
1043 | 1131 |
1044 void finish_phi (jit_block *pred); | |
1045 | |
1046 void do_construct_ssa (jit_convert& convert, size_t visit_count); | |
1047 | |
1048 void create_dom_tree (size_t visit_count); | 1132 void create_dom_tree (size_t visit_count); |
1049 | 1133 |
1050 jit_block *idom_intersect (jit_block *b); | 1134 jit_block *idom_intersect (jit_block *b); |
1135 | |
1136 template <typename func_type0, typename func_type1> | |
1137 void do_visit_dom (size_t visit_count, func_type0 inorder, func_type1 postorder); | |
1051 | 1138 |
1052 static const size_t NO_ID = static_cast<size_t> (-1); | 1139 static const size_t NO_ID = static_cast<size_t> (-1); |
1053 size_t mvisit_count; | 1140 size_t mvisit_count; |
1054 size_t mid; | 1141 size_t mid; |
1055 jit_block *idom; | 1142 jit_block *idom; |
1058 std::string mname; | 1145 std::string mname; |
1059 instruction_list instructions; | 1146 instruction_list instructions; |
1060 mutable std::vector<llvm::BasicBlock *> mpred_llvm; | 1147 mutable std::vector<llvm::BasicBlock *> mpred_llvm; |
1061 }; | 1148 }; |
1062 | 1149 |
1150 // allow regular function pointers as well as pointers to members | |
1151 template <typename func_type> | |
1152 class jit_block_callback | |
1153 { | |
1154 public: | |
1155 jit_block_callback (func_type afunction) : function (afunction) {} | |
1156 | |
1157 void operator() (jit_block& block) | |
1158 { | |
1159 function (block); | |
1160 } | |
1161 private: | |
1162 func_type function; | |
1163 }; | |
1164 | |
1165 template <> | |
1166 class jit_block_callback<void (jit_block::*)(void)> | |
1167 { | |
1168 public: | |
1169 typedef void (jit_block::*func_type)(void); | |
1170 | |
1171 jit_block_callback (func_type afunction) : function (afunction) {} | |
1172 | |
1173 void operator() (jit_block& ablock) | |
1174 { | |
1175 (ablock.*function) (); | |
1176 } | |
1177 private: | |
1178 func_type function; | |
1179 }; | |
1180 | |
1181 template <typename func_type0, typename func_type1> | |
1182 void | |
1183 jit_block::do_visit_dom (size_t visit_count, func_type0 inorder, func_type1 postorder) | |
1184 { | |
1185 if (mvisit_count > visit_count) | |
1186 return; | |
1187 mvisit_count = visit_count + 1; | |
1188 | |
1189 jit_block_callback<func_type0> inorder_cb (inorder); | |
1190 inorder_cb (*this); | |
1191 | |
1192 for (size_t i = 0; i < dom_succ.size (); ++i) | |
1193 dom_succ[i]->do_visit_dom (visit_count, inorder, postorder); | |
1194 | |
1195 jit_block_callback<func_type1> postorder_cb (postorder); | |
1196 postorder_cb (*this); | |
1197 } | |
1063 | 1198 |
1064 | 1199 |
1065 // A non-ssa variable | 1200 // A non-ssa variable |
1066 class | 1201 class |
1067 jit_variable : public jit_value | 1202 jit_variable : public jit_value |
1068 { | 1203 { |
1069 public: | 1204 public: |
1070 jit_variable (const std::string& aname) : mname (aname) {} | 1205 jit_variable (const std::string& aname) : mname (aname), mlast_use (0) {} |
1071 | 1206 |
1072 const std::string &name (void) const { return mname; } | 1207 const std::string &name (void) const { return mname; } |
1073 | 1208 |
1074 // manipulate the value_stack, for use during SSA construction. The top of the | 1209 // manipulate the value_stack, for use during SSA construction. The top of the |
1075 // value stack represents the current value for this variable | 1210 // value stack represents the current value for this variable |
1081 jit_value *top (void) const | 1216 jit_value *top (void) const |
1082 { | 1217 { |
1083 return value_stack.top (); | 1218 return value_stack.top (); |
1084 } | 1219 } |
1085 | 1220 |
1086 void push (jit_value *v) | 1221 void push (jit_instruction *v) |
1087 { | 1222 { |
1088 value_stack.push (v); | 1223 value_stack.push (v); |
1224 mlast_use = v; | |
1089 } | 1225 } |
1090 | 1226 |
1091 void pop (void) | 1227 void pop (void) |
1092 { | 1228 { |
1093 value_stack.pop (); | 1229 value_stack.pop (); |
1230 } | |
1231 | |
1232 jit_instruction *last_use (void) const | |
1233 { | |
1234 return mlast_use; | |
1235 } | |
1236 | |
1237 void stash_last_use (jit_instruction *instr) | |
1238 { | |
1239 mlast_use = instr; | |
1094 } | 1240 } |
1095 | 1241 |
1096 // blocks in which we are used | 1242 // blocks in which we are used |
1097 void use_blocks (jit_block::df_set& result) | 1243 void use_blocks (jit_block::df_set& result) |
1098 { | 1244 { |
1108 { | 1254 { |
1109 return print_indent (os, indent) << mname; | 1255 return print_indent (os, indent) << mname; |
1110 } | 1256 } |
1111 | 1257 |
1112 JIT_VALUE_ACCEPT (variable) | 1258 JIT_VALUE_ACCEPT (variable) |
1259 JIT_GEN_CASTS (variable) | |
1113 private: | 1260 private: |
1114 std::string mname; | 1261 std::string mname; |
1115 std::stack<jit_value *> value_stack; | 1262 std::stack<jit_value *> value_stack; |
1263 jit_instruction *mlast_use; | |
1116 }; | 1264 }; |
1117 | 1265 |
1118 class | 1266 class |
1119 jit_phi : public jit_instruction | 1267 jit_phi : public jit_instruction |
1120 { | 1268 { |
1121 public: | 1269 public: |
1122 jit_phi (jit_variable *avariable, size_t npred) | 1270 jit_phi (jit_variable *avariable, size_t npred) |
1123 : jit_instruction (npred) | 1271 : jit_instruction (npred) |
1124 { | 1272 { |
1125 stash_tag (avariable); | 1273 stash_tag (avariable); |
1274 } | |
1275 | |
1276 virtual bool dead (void) const | |
1277 { | |
1278 return use_count () == 0; | |
1279 } | |
1280 | |
1281 virtual bool almost_dead (void) const | |
1282 { | |
1283 return use_count () <= 1; | |
1126 } | 1284 } |
1127 | 1285 |
1128 virtual bool infer (void) | 1286 virtual bool infer (void) |
1129 { | 1287 { |
1130 jit_type *infered = 0; | 1288 jit_type *infered = 0; |
1165 | 1323 |
1166 return os; | 1324 return os; |
1167 } | 1325 } |
1168 | 1326 |
1169 JIT_VALUE_ACCEPT (phi); | 1327 JIT_VALUE_ACCEPT (phi); |
1328 JIT_GEN_CASTS (phi) | |
1170 }; | 1329 }; |
1171 | 1330 |
1172 class | 1331 class |
1173 jit_terminator : public jit_instruction | 1332 jit_terminator : public jit_instruction |
1174 { | 1333 { |
1195 { | 1354 { |
1196 return sucessor (idx)->short_print (os); | 1355 return sucessor (idx)->short_print (os); |
1197 } | 1356 } |
1198 | 1357 |
1199 virtual size_t sucessor_count (void) const = 0; | 1358 virtual size_t sucessor_count (void) const = 0; |
1359 | |
1360 JIT_GEN_CASTS (terminator) | |
1200 }; | 1361 }; |
1201 | 1362 |
1202 class | 1363 class |
1203 jit_break : public jit_terminator | 1364 jit_break : public jit_terminator |
1204 { | 1365 { |
1218 print_indent (os, indent) << "break: "; | 1379 print_indent (os, indent) << "break: "; |
1219 return print_sucessor (os); | 1380 return print_sucessor (os); |
1220 } | 1381 } |
1221 | 1382 |
1222 JIT_VALUE_ACCEPT (break) | 1383 JIT_VALUE_ACCEPT (break) |
1384 JIT_GEN_CASTS (break) | |
1223 }; | 1385 }; |
1224 | 1386 |
1225 class | 1387 class |
1226 jit_cond_break : public jit_terminator | 1388 jit_cond_break : public jit_terminator |
1227 { | 1389 { |
1256 print_sucessor (os, 0) << ", "; | 1418 print_sucessor (os, 0) << ", "; |
1257 return print_sucessor (os, 1); | 1419 return print_sucessor (os, 1); |
1258 } | 1420 } |
1259 | 1421 |
1260 JIT_VALUE_ACCEPT (cond_break) | 1422 JIT_VALUE_ACCEPT (cond_break) |
1423 JIT_GEN_CASTS (cond_break) | |
1261 }; | 1424 }; |
1262 | 1425 |
1263 class | 1426 class |
1264 jit_call : public jit_instruction | 1427 jit_call : public jit_instruction |
1265 { | 1428 { |
1277 jit_call (const jit_function& (*afunction) (void), | 1440 jit_call (const jit_function& (*afunction) (void), |
1278 jit_value *arg0, jit_value *arg1) : jit_instruction (arg0, arg1), | 1441 jit_value *arg0, jit_value *arg1) : jit_instruction (arg0, arg1), |
1279 mfunction (afunction ()) {} | 1442 mfunction (afunction ()) {} |
1280 | 1443 |
1281 const jit_function& function (void) const { return mfunction; } | 1444 const jit_function& function (void) const { return mfunction; } |
1445 | |
1446 bool has_side_effects (void) const | |
1447 { | |
1448 return overload ().side_effects; | |
1449 } | |
1282 | 1450 |
1283 const jit_function::overload& overload (void) const | 1451 const jit_function::overload& overload (void) const |
1284 { | 1452 { |
1285 return mfunction.get_overload (argument_types ()); | 1453 return mfunction.get_overload (argument_types ()); |
1286 } | 1454 } |
1300 os << ", "; | 1468 os << ", "; |
1301 } | 1469 } |
1302 return os << ")"; | 1470 return os << ")"; |
1303 } | 1471 } |
1304 | 1472 |
1473 virtual bool dead (void) const; | |
1474 | |
1475 virtual bool almost_dead (void) const; | |
1476 | |
1305 virtual bool infer (void); | 1477 virtual bool infer (void); |
1306 | 1478 |
1307 JIT_VALUE_ACCEPT (call) | 1479 JIT_VALUE_ACCEPT (call) |
1480 JIT_GEN_CASTS (call) | |
1308 private: | 1481 private: |
1309 const jit_function& mfunction; | 1482 const jit_function& mfunction; |
1310 }; | 1483 }; |
1311 | 1484 |
1312 class | 1485 class |
1337 short_print (os); | 1510 short_print (os); |
1338 return os; | 1511 return os; |
1339 } | 1512 } |
1340 | 1513 |
1341 JIT_VALUE_ACCEPT (extract_argument) | 1514 JIT_VALUE_ACCEPT (extract_argument) |
1515 JIT_GEN_CASTS (extract_argument) | |
1342 }; | 1516 }; |
1343 | 1517 |
1344 class | 1518 class |
1345 jit_store_argument : public jit_instruction | 1519 jit_store_argument : public jit_instruction |
1346 { | 1520 { |
1383 short_print (os) << " = "; | 1557 short_print (os) << " = "; |
1384 return res->short_print (os); | 1558 return res->short_print (os); |
1385 } | 1559 } |
1386 | 1560 |
1387 JIT_VALUE_ACCEPT (store_argument) | 1561 JIT_VALUE_ACCEPT (store_argument) |
1562 JIT_GEN_CASTS (store_argument) | |
1388 }; | 1563 }; |
1389 | 1564 |
1390 class | 1565 class |
1391 jit_ir_walker | 1566 jit_ir_walker |
1392 { | 1567 { |
1393 public: | 1568 public: |
1394 virtual ~jit_ir_walker () {} | 1569 virtual ~jit_ir_walker () {} |
1395 | 1570 |
1396 #define JIT_METH(clname) \ | 1571 #define JIT_METH(clname) \ |
1397 virtual void visit (jit_ ## clname&) = 0 | 1572 virtual void visit (jit_ ## clname&) = 0; |
1398 | 1573 |
1399 JIT_VISIT_IR_CLASSES; | 1574 JIT_VISIT_IR_CLASSES; |
1400 | 1575 |
1401 #undef JIT_METH | 1576 #undef JIT_METH |
1402 }; | 1577 }; |
1546 T *ret = new T(arg0, arg1, arg2); | 1721 T *ret = new T(arg0, arg1, arg2); |
1547 track_value (ret); | 1722 track_value (ret); |
1548 return ret; | 1723 return ret; |
1549 } | 1724 } |
1550 private: | 1725 private: |
1726 typedef std::list<jit_block *> block_list; | |
1727 typedef block_list::iterator block_iterator; | |
1728 | |
1551 std::vector<std::pair<std::string, bool> > arguments; | 1729 std::vector<std::pair<std::string, bool> > arguments; |
1552 type_bound_vector bounds; | 1730 type_bound_vector bounds; |
1553 | 1731 |
1554 // used instead of return values from visit_* functions | 1732 // used instead of return values from visit_* functions |
1555 jit_instruction *result; | 1733 jit_instruction *result; |
1594 constants.push_back (value); | 1772 constants.push_back (value); |
1595 all_values.push_back (value); | 1773 all_values.push_back (value); |
1596 } | 1774 } |
1597 | 1775 |
1598 void construct_ssa (jit_block *final_block); | 1776 void construct_ssa (jit_block *final_block); |
1777 | |
1778 static void do_construct_ssa (jit_block& block); | |
1779 | |
1780 void place_releases (void); | |
1599 | 1781 |
1600 void print_blocks (const std::string& header) | 1782 void print_blocks (const std::string& header) |
1601 { | 1783 { |
1602 std::cout << "-------------------- " << header << " --------------------\n"; | 1784 std::cout << "-------------------- " << header << " --------------------\n"; |
1603 for (std::list<jit_block *>::iterator iter = blocks.begin (); | 1785 for (std::list<jit_block *>::iterator iter = blocks.begin (); |
1619 (*iter)->print_dom (std::cout); | 1801 (*iter)->print_dom (std::cout); |
1620 } | 1802 } |
1621 std::cout << std::endl; | 1803 std::cout << std::endl; |
1622 } | 1804 } |
1623 | 1805 |
1624 typedef std::list<jit_block *> break_list; | |
1625 | |
1626 bool breaking; // true if we are breaking OR continuing | 1806 bool breaking; // true if we are breaking OR continuing |
1627 break_list breaks; | 1807 block_list breaks; |
1628 break_list continues; | 1808 block_list continues; |
1629 | 1809 |
1630 void finish_breaks (jit_block *dest, const break_list& lst); | 1810 void finish_breaks (jit_block *dest, const block_list& lst); |
1811 | |
1812 struct release_placer | |
1813 { | |
1814 release_placer (jit_convert& aconvert) : convert (aconvert) {} | |
1815 | |
1816 jit_convert& convert; | |
1817 | |
1818 void operator() (jit_block& block); | |
1819 }; | |
1631 | 1820 |
1632 // this case is much simpler, just convert from the jit ir to llvm | 1821 // this case is much simpler, just convert from the jit ir to llvm |
1633 class | 1822 class |
1634 convert_llvm : public jit_ir_walker | 1823 convert_llvm : public jit_ir_walker |
1635 { | 1824 { |
1646 #undef JIT_METH | 1835 #undef JIT_METH |
1647 private: | 1836 private: |
1648 // name -> llvm argument | 1837 // name -> llvm argument |
1649 std::map<std::string, llvm::Value *> arguments; | 1838 std::map<std::string, llvm::Value *> arguments; |
1650 | 1839 |
1840 void finish_phi (jit_instruction *phi); | |
1651 | 1841 |
1652 void visit (jit_value *jvalue) | 1842 void visit (jit_value *jvalue) |
1653 { | 1843 { |
1654 return visit (*jvalue); | 1844 return visit (*jvalue); |
1655 } | 1845 } |