# HG changeset patch # User Max Brister # Date 1338311246 18000 # Node ID 8697e3e9d77a2534990578f717e049bbbd04ccf8 # Parent d4d9a64db6aa78c243e83af853992084fd084849 Properly cleanup the low level IR diff --git a/src/pt-jit.cc b/src/pt-jit.cc --- a/src/pt-jit.cc +++ b/src/pt-jit.cc @@ -616,6 +616,16 @@ } // -------------------- jit_value -------------------- +jit_value::~jit_value (void) +{ + while (use_head) + { + jit_instruction *user = use_head->user (); + size_t idx = use_head->index (); + user->stash_argument (idx, 0); + } +} + #define JIT_METH(clname) \ void \ jit_ ## clname::accept (jit_ir_walker& walker) \ @@ -733,18 +743,15 @@ } jit_phi * -jit_block::search_phi (const std::string& tag_name, jit_value *adefault) +jit_block::search_phi (const std::string& tag_name) { - jit_phi *ret; + jit_phi *ret = 0; for (iterator iter = begin (); iter != end () && (ret = dynamic_cast (*iter)); ++iter) if (ret->tag () == tag_name) return ret; - ret = new jit_phi (pred_count (), adefault); - ret->stash_tag (tag_name); - prepend (ret); - return ret; + return 0; } llvm::BasicBlock * @@ -788,21 +795,21 @@ { jit_instruction::reset_ids (); - jit_block *entry_block = new jit_block ("body"); + jit_block *entry_block = create ("body"); block = entry_block; blocks.push_back (block); - toplevel_map tlevel (block); + toplevel_map tlevel (*this, block); variables = &tlevel; - final_block = new jit_block ("final"); + final_block = create ("final"); visit (tee); blocks.push_back (final_block); - block->append (new jit_break (final_block)); + block->append (create (final_block)); for (variable_map::iterator iter = variables->begin (); iter != variables->end (); ++iter) - final_block->append (new jit_store_argument (iter->first, iter->second)); + final_block->append (create (iter->first, iter->second)); // FIXME: Maybe we should remove dead code here? @@ -868,6 +875,13 @@ } } +jit_convert::~jit_convert (void) +{ + for (std::list::iterator iter = all_values.begin (); + iter != all_values.end (); ++iter) + delete *iter; +} + void jit_convert::visit_anon_fcn_handle (tree_anon_fcn_handle&) { @@ -894,7 +908,7 @@ jit_value *rhsv = visit (rhs); const jit_function& fn = jit_typeinfo::binary_op (be.op_type ()); - result = block->append (new jit_call (fn, lhsv, rhsv)); + result = block->append (create (fn, lhsv, rhsv)); } void @@ -977,24 +991,22 @@ fail (); std::string lhs_name = lhs->name (); - jit_block *body = new jit_block ("for_body"); + jit_block *body = create ("for_body"); blocks.push_back (body); - jit_block *tail = new jit_block ("for_tail"); - unwind_protect prot_tail; - prot_tail.add_delete (tail); // incase we fail before adding tail to blocks + jit_block *tail = create ("for_tail"); // do control expression, iter init, and condition check in prev_block (block) jit_value *control = visit (cmd.control_expr ()); - jit_call *init_iter = new jit_call (jit_typeinfo::for_init, control); + jit_call *init_iter = create (jit_typeinfo::for_init, control); init_iter->stash_tag ("#iter"); block->append (init_iter); - jit_value *check = block->append (new jit_call (jit_typeinfo::for_check, - control, init_iter)); - block->append (new jit_cond_break (check, body, tail)); + jit_value *check = block->append (create (jit_typeinfo::for_check, + control, init_iter)); + block->append (create (check, body, tail)); // we need to do iter phi manually, for_map handles the rest - jit_phi *iter_phi = new jit_phi (2); + jit_phi *iter_phi = create (2); iter_phi->stash_tag ("#iter"); iter_phi->stash_argument (0, init_iter); body->append (iter_phi); @@ -1005,7 +1017,7 @@ block = body; // first thing we do in the for loop is bind our index from our itertor - jit_call *idx_rhs = new jit_call (jit_typeinfo::for_index, control, iter_phi); + jit_call *idx_rhs = create (jit_typeinfo::for_index, control, iter_phi); block->append (idx_rhs); idx_rhs->stash_tag (lhs_name); do_assign (lhs_name, idx_rhs, false); @@ -1015,28 +1027,27 @@ // increment iterator, check conditional, and repeat const jit_function& add_fn = jit_typeinfo::binary_op (octave_value::op_add); - jit_call *iter_inc = new jit_call (add_fn, iter_phi, - get_const (1)); + jit_call *iter_inc = create (add_fn, iter_phi, + create (1)); iter_inc->stash_tag ("#iter"); block->append (iter_inc); - check = block->append (new jit_call (jit_typeinfo::for_check, control, - iter_inc)); - block->append (new jit_cond_break (check, body, tail)); + check = block->append (create (jit_typeinfo::for_check, control, + iter_inc)); + block->append (create (check, body, tail)); iter_phi->stash_argument (1, iter_inc); body_vars.finish_phi (*variables); merge (tail, *merge_vars, block, body_vars); blocks.push_back (tail); - prot_tail.discard (); block = tail; variables = merge_vars; - iter_phi = new jit_phi (2); + iter_phi = create (2); iter_phi->stash_tag ("#iter"); iter_phi->stash_argument (0, init_iter); iter_phi->stash_argument (1, iter_inc); block->append (iter_phi); - block->append (new jit_call (jit_typeinfo::release, iter_phi)); + block->append (create (jit_typeinfo::release, iter_phi)); } void @@ -1080,7 +1091,7 @@ { const jit_function& fn = jit_typeinfo::grab (); jit_value *var = variables->get (ti.name ()); - result = block->append (new jit_call (fn, var)); + result = block->append (create (fn, var)); } void @@ -1149,13 +1160,12 @@ { tree_if_clause *tic = *iter; if (tic->is_else_clause ()) - entry_blocks[i] = new jit_block ("else"); + entry_blocks[i] = create ("else"); else - entry_blocks[i] = new jit_block ("ifelse_cond"); - cleanup_blocks.push_back (entry_blocks[i]); + entry_blocks[i] = create ("ifelse_cond"); } - jit_block *tail = new jit_block ("if_tail"); + jit_block *tail = create ("if_tail"); if (! last_else) entry_blocks[entry_blocks.size () - 1] = tail; @@ -1178,11 +1188,11 @@ tree_expression *expr = tic->condition (); jit_value *cond = visit (expr); - jit_block *body = new jit_block (i == 0 ? "if_body" : "ifelse_body"); + jit_block *body = create (i == 0 ? "if_body" : "ifelse_body"); blocks.push_back (body); - jit_instruction *br = new jit_cond_break (cond, body, - entry_blocks[i + 1]); + jit_instruction *br = create (cond, body, + entry_blocks[i + 1]); block->append (br); block = body; @@ -1196,7 +1206,7 @@ branch_variables[i] = variables; branch_blocks[i] = block; - block->append (new jit_break (tail)); + block->append (create (tail)); } blocks.push_back (tail); @@ -1249,12 +1259,12 @@ if (v.is_real_scalar () && v.is_double_type ()) { double dv = v.double_value (); - result = get_const (dv); + result = create (dv); } else if (v.is_range ()) { Range rv = v.range_value (); - result = get_const (rv); + result = create (rv); } else fail (); @@ -1347,8 +1357,8 @@ // FIXME: ugly hack, we need to come up with a way to pass // nargout to visit_identifier const jit_function& fn = jit_typeinfo::print_value (); - jit_const_string *name = get_const (expr->name ()); - block->append (new jit_call (fn, name, expr_result)); + jit_const_string *name = create (expr->name ()); + block->append (create (fn, name, expr_result)); } } } @@ -1413,14 +1423,14 @@ { const jit_function& release = jit_typeinfo::release (); jit_value *current = variables->get (lhs); - block->append (new jit_call (release, current)); + block->append (create (release, current)); variables->set (lhs, rhs); if (print) { const jit_function& print_fn = jit_typeinfo::print_value (); - jit_const_string *name = get_const (lhs); - block->append (new jit_call (print_fn, name, rhs)); + jit_const_string *name = create (lhs); + block->append (create (print_fn, name, rhs)); } } @@ -1440,6 +1450,7 @@ jit_block *incomming_block, const variable_map& incomming_vars) { + size_t pred_count = merge_block->pred_count (); size_t merge_idx = merge_block->pred_index (incomming_block); for (variable_map::const_iterator iter = incomming_vars.begin (); iter != incomming_vars.end (); ++iter) @@ -1453,7 +1464,13 @@ jit_phi *phi = dynamic_cast (merge_val); if (! (phi && phi->parent () == merge_block)) { - phi = merge_block->search_phi (vname, merge_val); + phi = merge_block->search_phi (vname); + if (! phi) + { + phi = create (pred_count, merge_val); + merge_block->prepend (phi); + } + merge_vars.set (vname, phi); } @@ -1471,7 +1488,7 @@ jit_block *entry = block (); octave_value val = symbol_table::find (name); jit_type *type = jit_typeinfo::type_of (val); - jit_instruction *ret = new jit_extract_argument (type, name); + jit_instruction *ret = convert.create (type, name); return vars[name] = entry->prepend (ret); } diff --git a/src/pt-jit.h b/src/pt-jit.h --- a/src/pt-jit.h +++ b/src/pt-jit.h @@ -513,7 +513,7 @@ public: jit_value (void) : llvm_value (0), ty (0), use_head (0), myuse_count (0) {} - virtual ~jit_value (void) {} + virtual ~jit_value (void); jit_type *type (void) const { return ty; } @@ -568,7 +568,6 @@ private: jit_type *ty; jit_use *use_head; - jit_use *use_tail; size_t myuse_count; }; @@ -865,13 +864,6 @@ jit_block (const std::string& aname) : mname (aname) {} - virtual ~jit_block () - { - for (instruction_list::iterator iter = instructions.begin (); - iter != instructions.end (); ++iter) - delete *iter; - } - const std::string& name (void) const { return mname; } jit_instruction *prepend (jit_instruction *instr); @@ -926,8 +918,8 @@ const_iterator end (void) const { return instructions.begin (); } // search for the phi function with the given tag_name, if no function - // exists then a new phi node is created - jit_phi *search_phi (const std::string& tag_name, jit_value *adefault); + // exists then null is returned + jit_phi *search_phi (const std::string& tag_name); virtual std::ostream& print (std::ostream& os, size_t indent) { @@ -1252,6 +1244,8 @@ jit_convert (llvm::Module *module, tree &tee); + ~jit_convert (void); + llvm::Function *get_function (void) const { return function; } const std::vector >& get_arguments(void) const @@ -1408,9 +1402,12 @@ toplevel_map : public variable_map { public: - toplevel_map (jit_block *aentry) : variable_map (0, aentry) {} + toplevel_map (jit_convert& aconvert, jit_block *aentry) + : variable_map (0, aentry), convert (aconvert) {} protected: virtual jit_value *insert (const std::string& name, jit_value *pval); + private: + jit_convert& convert; }; class @@ -1476,12 +1473,12 @@ std::list blocks; - std::list cleanup_blocks; - std::list worklist; std::list constants; + std::list all_values; + void do_assign (const std::string& lhs, jit_value *rhs, bool print); jit_value *visit (tree *tee) { return visit (*tee); } @@ -1494,14 +1491,46 @@ worklist.push_back (use->user ()); } - template - CONST_T *get_const (typename CONST_T::pass_t v) + // this would be easier with variadic templates + template + T *create (void) + { + T *ret = new T(); + track_value (ret); + return ret; + } + + template + T *create (const ARG0& arg0) { - CONST_T *ret = new CONST_T (v); - constants.push_back (ret); + T *ret = new T(arg0); + track_value (ret); + return ret; + } + + template + T *create (const ARG0& arg0, const ARG1& arg1) + { + T *ret = new T(arg0, arg1); + track_value (ret); return ret; } + template + T *create (const ARG0& arg0, const ARG1& arg1, const ARG2& arg2) + { + T *ret = new T(arg0, arg1, arg2); + track_value (ret); + return ret; + } + + void track_value (jit_value *value) + { + if (value->type ()) + constants.push_back (value); + all_values.push_back (value); + } + // place phi nodes in the current block to merge ref with variables // we assume the same number of deffinitions void merge (jit_block *merge_block, variable_map& merge_vars,