# HG changeset patch # User Max Brister # Date 1339212717 18000 # Node ID 591aeec5c5200c20c260ea340afedb3815f61aef # Parent c0a5ab3b92786fe64f50944874c991ef84caa6c5 Remove uneeded error checks diff --git a/src/pt-jit.cc b/src/pt-jit.cc --- a/src/pt-jit.cc +++ b/src/pt-jit.cc @@ -356,7 +356,7 @@ fn->arg_begin (), ++fn->arg_begin ()); builder.CreateRet (ret); - binary_ops[op].add_overload (fn, true, true, any, any, any); + binary_ops[op].add_overload (fn, true, any, any, any); } llvm::Type *void_t = llvm::Type::getVoidTy (context); @@ -365,30 +365,30 @@ fn = create_function ("octave_jit_grab_any", any, any); engine->addGlobalMapping (fn, reinterpret_cast(&octave_jit_grab_any)); - grab_fn.add_overload (fn, false, false, any, any); + grab_fn.add_overload (fn, false, any, any); grab_fn.stash_name ("grab"); // grab scalar fn = create_identity (scalar); - grab_fn.add_overload (fn, false, false, scalar, scalar); + grab_fn.add_overload (fn, false, scalar, scalar); // grab index fn = create_identity (index); - grab_fn.add_overload (fn, false, false, index, index); + grab_fn.add_overload (fn, false, index, index); // release any fn = create_function ("octave_jit_release_any", void_t, any->to_llvm ()); engine->addGlobalMapping (fn, reinterpret_cast(&octave_jit_release_any)); - release_fn.add_overload (fn, false, false, 0, any); + release_fn.add_overload (fn, false, 0, any); release_fn.stash_name ("release"); // release scalar fn = create_identity (scalar); - release_fn.add_overload (fn, false, false, 0, scalar); + release_fn.add_overload (fn, false, 0, scalar); // release index fn = create_identity (index); - release_fn.add_overload (fn, false, false, 0, index); + release_fn.add_overload (fn, false, 0, index); // now for binary scalar operations // FIXME: Finish all operations @@ -428,7 +428,7 @@ llvm::Value *ret = builder.CreateFDiv (fn->arg_begin (), ++fn->arg_begin ()); builder.CreateRet (ret); - jit_function::overload ol (fn, true, true, scalar, scalar, scalar); + jit_function::overload ol (fn, true, scalar, scalar, scalar); binary_ops[octave_value::op_div].add_overload (ol); binary_ops[octave_value::op_el_div].add_overload (ol); } @@ -444,7 +444,7 @@ fn->arg_begin ()); builder.CreateRet (ret); - jit_function::overload ol (fn, true, true, scalar, scalar, scalar); + jit_function::overload ol (fn, true, scalar, scalar, scalar); binary_ops[octave_value::op_ldiv].add_overload (ol); binary_ops[octave_value::op_el_ldiv].add_overload (ol); } @@ -469,7 +469,7 @@ builder.CreateRet (zero); } llvm::verifyFunction (*fn); - for_init_fn.add_overload (fn, false, false, index, range); + for_init_fn.add_overload (fn, false, index, range); // bounds check for for loop for_check_fn.stash_name ("for_check"); @@ -485,7 +485,7 @@ builder.CreateRet (ret); } llvm::verifyFunction (*fn); - for_check_fn.add_overload (fn, false, false, boolean, range, index); + for_check_fn.add_overload (fn, false, boolean, range, index); // index variabe for for loop for_index_fn.stash_name ("for_index"); @@ -505,7 +505,7 @@ builder.CreateRet (ret); } llvm::verifyFunction (*fn); - for_index_fn.add_overload (fn, false, false, scalar, range, index); + for_index_fn.add_overload (fn, false, scalar, range, index); // logically true logically_true_fn.stash_name ("logically_true"); @@ -534,14 +534,14 @@ builder.CreateRet (ret); } llvm::verifyFunction (*fn); - logically_true_fn.add_overload (fn, true, false, boolean, scalar); + logically_true_fn.add_overload (fn, true, boolean, scalar); fn = create_function ("octave_logically_true_bool", boolean, boolean); body = llvm::BasicBlock::Create (context, "body", fn); builder.SetInsertPoint (body); builder.CreateRet (fn->arg_begin ()); llvm::verifyFunction (*fn); - logically_true_fn.add_overload (fn, false, false, boolean, boolean); + logically_true_fn.add_overload (fn, false, boolean, boolean); // make_range // FIXME: May be benificial to implement all in LLVM @@ -572,7 +572,7 @@ builder.CreateRet (rng); } llvm::verifyFunction (*fn); - make_range_fn.add_overload (fn, false, false, range, scalar, scalar, scalar); + make_range_fn.add_overload (fn, false, range, scalar, scalar, scalar); casts[any->type_id ()].stash_name ("(any)"); casts[scalar->type_id ()].stash_name ("(scalar)"); @@ -580,20 +580,20 @@ // cast any <- scalar fn = create_function ("octave_jit_cast_any_scalar", any, scalar); engine->addGlobalMapping (fn, reinterpret_cast (&octave_jit_cast_any_scalar)); - casts[any->type_id ()].add_overload (fn, false, false, any, scalar); + casts[any->type_id ()].add_overload (fn, false, any, scalar); // cast scalar <- any fn = create_function ("octave_jit_cast_scalar_any", scalar, any); engine->addGlobalMapping (fn, reinterpret_cast (&octave_jit_cast_scalar_any)); - casts[scalar->type_id ()].add_overload (fn, false, false, scalar, any); + casts[scalar->type_id ()].add_overload (fn, false, scalar, any); // cast any <- any fn = create_identity (any); - casts[any->type_id ()].add_overload (fn, false, false, any, any); + casts[any->type_id ()].add_overload (fn, false, any, any); // cast scalar <- scalar fn = create_identity (scalar); - casts[scalar->type_id ()].add_overload (fn, false, false, scalar, scalar); + casts[scalar->type_id ()].add_overload (fn, false, scalar, scalar); } void @@ -608,7 +608,7 @@ ty->to_llvm ()); engine->addGlobalMapping (fn, call); - jit_function::overload ol (fn, false, true, 0, string, ty); + jit_function::overload ol (fn, false, 0, string, ty); print_fn.add_overload (ol); } @@ -631,7 +631,7 @@ builder.CreateRet (ret); llvm::verifyFunction (*fn); - jit_function::overload ol(fn, false, false, ty, ty, ty); + jit_function::overload ol(fn, false, ty, ty, ty); binary_ops[op].add_overload (ol); } @@ -653,7 +653,7 @@ builder.CreateRet (ret); llvm::verifyFunction (*fn); - jit_function::overload ol (fn, false, false, boolean, ty, ty); + jit_function::overload ol (fn, false, boolean, ty, ty); binary_ops[op].add_overload (ol); } @@ -675,7 +675,7 @@ builder.CreateRet (ret); llvm::verifyFunction (*fn); - jit_function::overload ol (fn, false, false, boolean, ty, ty); + jit_function::overload ol (fn, false, boolean, ty, ty); binary_ops[op].add_overload (ol); } @@ -787,6 +787,7 @@ { if (mparent) mparent->remove (mlocation); + resize_arguments (0); } llvm::BasicBlock * @@ -878,12 +879,11 @@ return append (instr); } -jit_instruction * -jit_block::append (jit_instruction *instr) +void +jit_block::internal_append (jit_instruction *instr) { instructions.push_back (instr); instr->stash_parent (this, --instructions.end ()); - return instr; } jit_instruction * @@ -917,19 +917,19 @@ jit_block::pred (size_t idx) const { // FIXME: Make this O(1) - - // here we get the use in backwards order. This means we preserve phi - // information when new blocks are added assert (idx < use_count ()); jit_use *use; - size_t real_idx = use_count () - idx - 1; size_t i; - for (use = first_use (), i = 0; use && i < real_idx; ++i, - use = use->next ()); - + for (use = first_use (), i = 0; use && i < idx; ++i, use = use->next ()); return use->user_parent (); } +bool +jit_block::branch_alive (jit_block *asucc) const +{ + return terminator ()->alive (asucc); +} + size_t jit_block::pred_index (jit_block *apred) const { @@ -941,12 +941,12 @@ } void -jit_block::create_merge (llvm::Function *inside, size_t pred_idx) +jit_block::create_merge (llvm::Function *inside, jit_block *apred) { mpred_llvm.resize (pred_count ()); - jit_block *ipred = pred (pred_idx); - if (! mpred_llvm[pred_idx] && ipred->pred_count () > 1) + size_t pred_idx = pred_index (apred); + if (! mpred_llvm[pred_idx] && apred->pred_count () > 1) { llvm::BasicBlock *amerge; amerge = llvm::BasicBlock::Create (context, "phi_merge", inside, @@ -1122,20 +1122,99 @@ return i; } -// -------------------- jit_call -------------------- +// -------------------- jit_phi -------------------- bool -jit_call::dead (void) const +jit_phi::prune (void) { - return ! has_side_effects () && use_count () == 0; + jit_block *p = parent (); + size_t new_idx = 0; + for (size_t i = 0; i < argument_count (); ++i) + { + jit_block *inc = incomming (i); + if (inc->branch_alive (p)) + { + if (new_idx != i) + { + stash_argument (new_idx, argument (i)); + mincomming[new_idx] = mincomming[i]; + } + + ++new_idx; + } + } + + if (new_idx != argument_count ()) + { + resize_arguments (new_idx); + mincomming.resize (new_idx); + } + + assert (argument_count () > 0); + if (argument_count () == 1) + { + replace_with (argument (0)); + return true; + } + + return false; } bool -jit_call::almost_dead (void) const +jit_phi::infer (void) +{ + jit_block *p = parent (); + if (! p->alive ()) + return false; + + jit_type *infered = 0; + for (size_t i = 0; i < argument_count (); ++i) + { + jit_block *inc = mincomming[i]; + if (inc->branch_alive (p)) + infered = jit_typeinfo::join (infered, argument_type (i)); + } + + if (infered != type ()) + { + stash_type (infered); + return true; + } + + return false; +} + +// -------------------- jit_terminator -------------------- +bool +jit_terminator::alive (const jit_block *asucessor) const { - return ! has_side_effects () && use_count () <= 1; + size_t scount = sucessor_count (); + for (size_t i = 0; i < scount; ++i) + if (sucessor (i) == asucessor) + return malive[i]; + + panic_impossible (); } bool +jit_terminator::infer (void) +{ + if (! parent ()->alive ()) + return false; + + bool changed = false; + for (size_t i = 0; i < malive.size (); ++i) + if (! malive[i] && check_alive (i)) + { + changed = true; + malive[i] = true; + sucessor (i)->mark_alive (); + } + + return changed; +} + +// -------------------- jit_call -------------------- +bool jit_call::infer (void) { // FIXME: explain algorithm @@ -1173,6 +1252,7 @@ entry_block = create ("body"); final_block = create ("final"); blocks.push_back (entry_block); + entry_block->mark_alive (); block = entry_block; visit (tee); @@ -1207,9 +1287,17 @@ worklist.pop_front (); if (next->infer ()) - append_users (next); + { + // terminators need to be handles specially + if (jit_terminator *term = dynamic_cast (next)) + append_users_term (term); + else + append_users (next); + } } + remove_dead (); + place_releases (); #ifdef OCTAVE_JIT_DEBUG @@ -1270,12 +1358,13 @@ jit_value *rhsv = visit (rhs); const jit_function& fn = jit_typeinfo::binary_op (be.op_type ()); - result = block->append (create (fn, lhsv, rhsv)); - - jit_block *normal = create (block->name () + "a"); - block->append (create (normal, final_block)); + jit_call *call = block->append (create (fn, lhsv, rhsv)); + + jit_block *normal = create (block->name ()); + block->append (create (call, normal, final_block)); blocks.push_back (normal); block = normal; + result = call; } void @@ -1524,12 +1613,12 @@ { tree_expression *expr = tic->condition (); jit_value *cond = visit (expr); - jit_instruction *check = create (&jit_typeinfo::logically_true, cond); + jit_call *check = create (&jit_typeinfo::logically_true, cond); block->append (check); - jit_block *next = create (block->name () + "a"); + jit_block *next = create (block->name ()); blocks.push_back (next); - block->append (create (next, final_block)); + block->append (create (check, next, final_block)); block = next; jit_block *body = create (i == 0 ? "if_body" : "ifelse_body"); @@ -1806,6 +1895,24 @@ } void +jit_convert::append_users_term (jit_terminator *term) +{ + for (size_t i = 0; i < term->sucessor_count (); ++i) + { + if (term->alive (i)) + { + jit_block *succ = term->sucessor (i); + for (jit_block::iterator iter = succ->begin (); iter != succ->end () + && isa (*iter); ++iter) + worklist.push_back (*iter); + + if (succ->terminator ()) + worklist.push_back (succ->terminator ()); + } + } +} + +void jit_convert::merge_blocks (void) { for (block_list::iterator iter = blocks.begin (); iter != blocks.end (); @@ -1903,7 +2010,6 @@ for (size_t i = 0; i < block.succ_count (); ++i) { jit_block *finish = block.succ (i); - size_t pred_idx = finish->pred_index (&block); for (jit_block::iterator iter = finish->begin (); iter != finish->end () && isa (*iter);) @@ -1912,7 +2018,7 @@ jit_variable *var = phi->dest (); if (var->has_top ()) { - phi->stash_argument (pred_idx, var->top ()); + phi->add_incomming (&block, var->top ()); ++iter; } else @@ -1927,6 +2033,50 @@ } void +jit_convert::remove_dead () +{ + block_list::iterator biter; + for (biter = blocks.begin (); biter != blocks.end (); ++biter) + { + jit_block *b = *biter; + if (b->alive ()) + { + for (jit_block::iterator iter = b->begin (); iter != b->end () + && isa (*iter);) + { + jit_phi *phi = static_cast (*iter); + if (phi->prune ()) + iter = b->remove (iter); + else + ++iter; + } + } + } + + for (biter = blocks.begin (); biter != blocks.end ();) + { + jit_block *b = *biter; + if (b->alive ()) + { + // FIXME: A special case for jit_check_error, if we generalize to + // we will need to change! + jit_terminator *term = b->terminator (); + if (term && term->sucessor_count () == 2 && ! term->alive (1)) + { + jit_block *succ = term->sucessor (0); + term->remove (); + jit_break *abreak = b->append (create (succ)); + abreak->infer (); + } + + ++biter; + } + else + biter = blocks.erase (biter); + } +} + +void jit_convert::place_releases (void) { release_placer placer (*this); @@ -2056,9 +2206,9 @@ } void -jit_convert::convert_llvm::finish_phi (jit_instruction *phi) +jit_convert::convert_llvm::finish_phi (jit_instruction *aphi) { - jit_block *pblock = phi->parent (); + jit_phi *phi = static_cast (aphi); llvm::PHINode *llvm_phi = llvm::cast (phi->to_llvm ()); bool can_remove = ! phi->use_count (); @@ -2086,7 +2236,7 @@ jit_value *arg = phi->argument (i); if (arg->has_llvm () && phi->argument_type (i) != phi->type ()) { - llvm::BasicBlock *pred = pblock->pred_llvm (i); + llvm::BasicBlock *pred = phi->incomming_llvm (i); builder.SetInsertPoint (--pred->end ()); const jit_function::overload& ol = jit_typeinfo::get_release (phi->argument_type (i)); @@ -2106,7 +2256,7 @@ { for (size_t i = 0; i < phi->argument_count (); ++i) { - llvm::BasicBlock *pred = pblock->pred_llvm (i); + llvm::BasicBlock *pred = phi->incomming_llvm (i); if (phi->argument_type (i) == phi->type ()) llvm_phi->addIncoming (phi->argument_llvm (i), pred); else @@ -2249,7 +2399,7 @@ jit_block *parent = phi.parent (); for (size_t i = 0; i < phi.argument_count (); ++i) if (phi.argument_type (i) != phi.type ()) - parent->create_merge (function, i); + parent->create_merge (function, phi.incomming (i)); } void diff --git a/src/pt-jit.h b/src/pt-jit.h --- a/src/pt-jit.h +++ b/src/pt-jit.h @@ -172,26 +172,25 @@ struct overload { - overload (void) : function (0), can_error (true), result (0) {} + overload (void) : function (0), can_error (false), result (0) {} - overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0) : - function (f), can_error (e), side_effects (s), result (r), arguments (1) + overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0) : + function (f), can_error (e), result (r), arguments (1) { arguments[0] = arg0; } - overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0, - jit_type *arg1) : function (f), can_error (e), side_effects (s), + overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, + jit_type *arg1) : function (f), can_error (e), result (r), arguments (2) { arguments[0] = arg0; arguments[1] = arg1; } - overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0, + overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, jit_type *arg1, jit_type *arg2) : function (f), can_error (e), - side_effects (s), result (r), - arguments (3) + result (r), arguments (3) { arguments[0] = arg0; arguments[1] = arg1; @@ -200,7 +199,6 @@ llvm::Function *function; bool can_error; - bool side_effects; jit_type *result; std::vector arguments; }; @@ -210,23 +208,23 @@ add_overload (func, func.arguments); } - void add_overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0) + void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0) { - overload ol (f, e, s, r, arg0); + overload ol (f, e, r, arg0); add_overload (ol); } - void add_overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0, + void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, jit_type *arg1) { - overload ol (f, e, s, r, arg0, arg1); + overload ol (f, e, r, arg0, arg1); add_overload (ol); } - void add_overload (llvm::Function *f, bool e, bool s, jit_type *r, jit_type *arg0, + void add_overload (llvm::Function *f, bool e, jit_type *r, jit_type *arg0, jit_type *arg1, jit_type *arg2) { - overload ol (f, e, s, r, arg0, arg1, arg2); + overload ol (f, e, r, arg0, arg1, arg2); add_overload (ol); } @@ -598,8 +596,8 @@ { friend class jit_use; public: - jit_value (void) : llvm_value (0), ty (0), use_head (0), myuse_count (0), - mlast_use (0) {} + jit_value (void) : llvm_value (0), ty (0), use_head (0), use_tail (0), + myuse_count (0), mlast_use (0) {} virtual ~jit_value (void); @@ -662,7 +660,7 @@ } protected: - std::ostream& print_indent (std::ostream& os, size_t indent) const + std::ostream& print_indent (std::ostream& os, size_t indent = 0) const { for (size_t i = 0; i < indent * 8; ++i) os << " "; @@ -673,6 +671,7 @@ private: jit_type *ty; jit_use *use_head; + jit_use *use_tail; size_t myuse_count; jit_instruction *mlast_use; }; @@ -721,11 +720,13 @@ { if (mvalue->use_head) { - mvalue->use_head->mprev = this; - mnext = mvalue->use_head; + mvalue->use_tail->mnext = this; + mprev = mvalue->use_tail; } + else + mvalue->use_head = this; - mvalue->use_head = this; + mvalue->use_tail = this; ++mvalue->myuse_count; } @@ -744,6 +745,9 @@ if (this == mvalue->use_head) mvalue->use_head = mnext; + if (this == mvalue->use_tail) + mvalue->use_tail = mprev; + if (mprev) mprev->mnext = mnext; @@ -874,10 +878,6 @@ const std::vector& argument_types (void) const { return already_infered; } - virtual bool dead (void) const { return false; } - - virtual bool almost_dead (void) const { return false; } - virtual void push_variable (void) {} virtual void pop_variable (void) {} @@ -943,7 +943,7 @@ PASS_T value (void) const { return mvalue; } - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { print_indent (os, indent); jit_print (os, type ()) << ": "; @@ -972,10 +972,17 @@ typedef df_set::const_iterator df_iterator; jit_block (const std::string& aname) : mvisit_count (0), mid (NO_ID), idom (0), - mname (aname), mdead (false) + mname (aname), mdead (false), + malive (false) {} - virtual bool dead (void) const { return mdead; } + // if a block is alive, then it might be visited during execution + bool alive (void) const { return malive; } + + void mark_alive (void) { malive = true; } + + // dead blocks have already been removed from the CFG + bool dead (void) const { return mdead; } void mark_dead (void) { mdead = true; } @@ -991,7 +998,12 @@ jit_instruction *prepend_after_phi (jit_instruction *instr); - jit_instruction *append (jit_instruction *instr); + template + T *append (T *instr) + { + internal_append (instr); + return instr; + } jit_instruction *insert_before (iterator loc, jit_instruction *instr); @@ -1014,6 +1026,9 @@ return pred (idx)->terminator (); } + // is the jump from pred alive? + bool branch_alive (jit_block *asucc) const; + std::ostream& print_pred (std::ostream& os, size_t idx) const { return pred (idx)->short_print (os); @@ -1036,7 +1051,7 @@ size_t pred_index (jit_block *apred) const; // create llvm phi merge blocks for all predecessors (if required) - void create_merge (llvm::Function *inside, size_t pred_idx); + void create_merge (llvm::Function *inside, jit_block *apred); size_t pred_count (void) const { return use_count (); } @@ -1122,7 +1137,7 @@ // call pop_varaible on all instructions void pop_all (void); - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { print_indent (os, indent); short_print (os) << ": %pred = "; @@ -1157,6 +1172,8 @@ JIT_VALUE_ACCEPT (block) private: + void internal_append (jit_instruction *instr); + void compute_df (size_t visit_count); bool update_idom (size_t visit_count); @@ -1178,6 +1195,7 @@ instruction_list instructions; mutable std::vector mpred_llvm; bool mdead; + bool malive; }; // allow regular function pointers as well as pointers to members @@ -1283,7 +1301,7 @@ } } - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { return print_indent (os, indent) << mname; } @@ -1354,34 +1372,34 @@ { public: jit_phi (jit_variable *adest, size_t npred) : jit_assign_base (adest, npred) - {} - - virtual bool dead (void) const { - return use_count () == 0; + mincomming.reserve (npred); } - virtual bool almost_dead (void) const + // removes arguments form dead incomming jumps + bool prune (void); + + void add_incomming (jit_block *from, jit_value *value) { - return use_count () <= 1; + stash_argument (mincomming.size (), value); + mincomming.push_back (from); } - virtual bool infer (void) + jit_block *incomming (size_t i) const { - jit_type *infered = 0; - for (size_t i = 0; i < argument_count (); ++i) - infered = jit_typeinfo::join (infered, argument_type (i)); - - if (infered != type ()) - { - stash_type (infered); - return true; - } - - return false; + return mincomming[i]; } - virtual std::ostream& print (std::ostream& os, size_t indent) const + llvm::BasicBlock *incomming_llvm (size_t i) const + { + jit_block *inc = incomming (i); + jit_block *p = parent (); + return p->pred_llvm (inc); + } + + virtual bool infer (void); + + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { std::stringstream ss; print_indent (ss, indent); @@ -1417,21 +1435,28 @@ } JIT_VALUE_ACCEPT (phi); +private: + std::vector mincomming; }; class jit_terminator : public jit_instruction { public: - jit_terminator (jit_value *arg0) : jit_instruction (arg0) {} + jit_terminator (size_t asucessor_count, jit_value *arg0) + : jit_instruction (arg0), malive (asucessor_count, false) {} - jit_terminator (jit_value *arg0, jit_value *arg1) - : jit_instruction (arg0, arg1) {} + jit_terminator (size_t asucessor_count, jit_value *arg0, jit_value *arg1) + : jit_instruction (arg0, arg1), malive (asucessor_count, false) {} - jit_terminator (jit_value *arg0, jit_value *arg1, jit_value *arg2) - : jit_instruction (arg0, arg1, arg2) {} + jit_terminator (size_t asucessor_count, jit_value *arg0, jit_value *arg1, + jit_value *arg2) + : jit_instruction (arg0, arg1, arg2), malive (asucessor_count, false) {} - virtual jit_block *sucessor (size_t idx = 0) const = 0; + jit_block *sucessor (size_t idx = 0) const + { + return static_cast (argument (idx)); + } // return either our sucessors block directly, or the phi merge block // between us and our sucessor @@ -1446,27 +1471,36 @@ std::ostream& print_sucessor (std::ostream& os, size_t idx = 0) const { + if (alive (idx)) + os << "[live] "; + else + os << "[dead] "; + return sucessor (idx)->short_print (os); } - virtual size_t sucessor_count (void) const = 0; + // Check if the jump to sucessor is live + bool alive (const jit_block *asucessor) const; + bool alive (size_t idx) const { return malive[idx]; } + + size_t sucessor_count (void) const { return malive.size (); } + + virtual bool infer (void); +protected: + virtual bool check_alive (size_t) const { return true; } +private: + std::vector malive; }; class jit_break : public jit_terminator { public: - jit_break (jit_block *succ) : jit_terminator (succ) {} + jit_break (jit_block *succ) : jit_terminator (1, succ) {} - jit_block *sucessor (size_t idx = 0) const - { - jit_value *arg = argument (idx); - return static_cast (arg); - } + virtual size_t sucessor_count (void) const { return 1; } - size_t sucessor_count (void) const { return 1; } - - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { print_indent (os, indent) << "break: "; return print_sucessor (os); @@ -1480,9 +1514,9 @@ { public: jit_cond_break (jit_value *c, jit_block *ctrue, jit_block *cfalse) - : jit_terminator (c, ctrue, cfalse) {} + : jit_terminator (2, ctrue, cfalse, c) {} - jit_value *cond (void) const { return argument (0); } + jit_value *cond (void) const { return argument (2); } std::ostream& print_cond (std::ostream& os) const { @@ -1494,15 +1528,9 @@ return cond ()->to_llvm (); } - jit_block *sucessor (size_t idx) const - { - jit_value *arg = argument (idx + 1); - return static_cast (arg); - } + virtual size_t sucessor_count (void) const { return 2; } - size_t sucessor_count (void) const { return 2; } - - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { print_indent (os, indent) << "cond_break: "; print_cond (os) << ", "; @@ -1518,7 +1546,8 @@ { public: jit_call (const jit_function& afunction, - jit_value *arg0) : jit_instruction (arg0), mfunction (afunction) {} + jit_value *arg0) : jit_instruction (arg0), mfunction (afunction) + {} jit_call (const jit_function& (*afunction) (void), jit_value *arg0) : jit_instruction (arg0), mfunction (afunction ()) {} @@ -1542,9 +1571,9 @@ const jit_function& function (void) const { return mfunction; } - bool has_side_effects (void) const + bool can_error (void) const { - return overload ().side_effects; + return overload ().can_error; } const jit_function::overload& overload (void) const @@ -1552,7 +1581,7 @@ return mfunction.get_overload (argument_types ()); } - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { print_indent (os, indent); @@ -1569,10 +1598,6 @@ return os << ")"; } - virtual bool dead (void) const; - - virtual bool almost_dead (void) const; - virtual bool infer (void); JIT_VALUE_ACCEPT (call) @@ -1587,24 +1612,27 @@ jit_check_error : public jit_terminator { public: - jit_check_error (jit_block *normal, jit_block *error) - : jit_terminator (normal, error) {} + jit_check_error (jit_call *acheck_for, jit_block *normal, jit_block *error) + : jit_terminator (2, normal, error, acheck_for) {} - jit_block *sucessor (size_t idx) const + jit_call *check_for (void) const { - return static_cast (argument (idx)); + return static_cast (argument (2)); } - size_t sucessor_count (void) const { return 2; } - virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { - print_indent (os, indent) << "check_error: normal: "; - print_sucessor (os, 0) << " error: "; + print_indent (os, indent) << "error_check " << *check_for () << ", "; + print_sucessor (os, 0) << ", "; return print_sucessor (os, 1); } JIT_VALUE_ACCEPT (jit_check_error) +protected: + virtual bool check_alive (size_t idx) const + { + return idx == 0 ? true : check_for ()->can_error (); + } }; class @@ -1627,7 +1655,7 @@ return jit_typeinfo::cast (type (), jit_typeinfo::get_any ()); } - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { print_indent (os, indent); @@ -1670,7 +1698,7 @@ return result ()->to_llvm (); } - virtual std::ostream& print (std::ostream& os, size_t indent) const + virtual std::ostream& print (std::ostream& os, size_t indent = 0) const { jit_value *res = result (); print_indent (os, indent) << "store "; @@ -1906,6 +1934,8 @@ worklist.push_back (use->user ()); } + void append_users_term (jit_terminator *term); + void track_value (jit_value *value) { if (value->type ()) @@ -1919,6 +1949,8 @@ static void do_construct_ssa (jit_block& block); + void remove_dead (); + void place_releases (void); void print_blocks (const std::string& header)