changeset 14945:591aeec5c520

Remove uneeded error checks
author Max Brister <max@2bass.com>
date Fri, 08 Jun 2012 22:31:57 -0500
parents c0a5ab3b9278
children 3564bb141396
files src/pt-jit.cc src/pt-jit.h
diffstat 2 files changed, 333 insertions(+), 151 deletions(-) [+]
line wrap: on
line diff
--- a/src/pt-jit.cc	Fri Jun 08 15:30:07 2012 -0500
+++ b/src/pt-jit.cc	Fri Jun 08 22:31:57 2012 -0500
@@ -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<void*>(&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<void*>(&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<void*> (&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<void*> (&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<jit_block> ("body");
   final_block = create<jit_block> ("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<jit_terminator *> (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<jit_call> (fn, lhsv, rhsv));
-
-  jit_block *normal = create<jit_block> (block->name () + "a");
-  block->append (create<jit_check_error> (normal, final_block));
+  jit_call *call = block->append (create<jit_call> (fn, lhsv, rhsv));
+
+  jit_block *normal = create<jit_block> (block->name ());
+  block->append (create<jit_check_error> (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_call> (&jit_typeinfo::logically_true, cond);
+          jit_call *check = create<jit_call> (&jit_typeinfo::logically_true, cond);
           block->append (check);
 
-          jit_block *next = create<jit_block> (block->name () + "a");
+          jit_block *next = create<jit_block> (block->name ());
           blocks.push_back (next);
-          block->append (create<jit_check_error> (next, final_block));
+          block->append (create<jit_check_error> (check, next, final_block));
           block = next;
 
           jit_block *body = create<jit_block> (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<jit_phi> (*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<jit_phi> (*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<jit_phi> (*iter);)
+            {
+              jit_phi *phi = static_cast<jit_phi *> (*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<jit_break> (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<jit_phi *> (aphi);
   llvm::PHINode *llvm_phi = llvm::cast<llvm::PHINode> (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
--- a/src/pt-jit.h	Fri Jun 08 15:30:07 2012 -0500
+++ b/src/pt-jit.h	Fri Jun 08 22:31:57 2012 -0500
@@ -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<jit_type*> 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<jit_type *>& 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 <typename T>
+  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<llvm::BasicBlock *> 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<jit_block *> 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<jit_block *> (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<bool> 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<jit_block *> (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<jit_block *> (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<jit_block *> (argument (idx));
+    return static_cast<jit_call *> (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)