diff --git a/src/main/scala/leon/FairZ3Solver.scala b/src/main/scala/leon/FairZ3Solver.scala
index 88d696f5bd41c4fe5091c1bc51ba1921ca6201fc..65b8ac217ca1f5893d9b9bab4f916a566f598af2 100644
--- a/src/main/scala/leon/FairZ3Solver.scala
+++ b/src/main/scala/leon/FairZ3Solver.scala
@@ -896,19 +896,27 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
 
 
   // the last return value is a map binding ite values to boolean switches
-  private def clausifyITE(formula : Expr) : (Expr, List[Expr], Map[Identifier,Identifier]) = {
+  private def clausifyITE(formula : Expr) : (Expr, List[Expr], Map[Identifier,Identifier], Seq[(Identifier, Boolean)]) = {
     var newClauses : List[Expr] = Nil
     var ite2Bools : Map[Identifier,Identifier] = Map.empty
+    var guards: List[(Identifier, Boolean)] = List()
 
     def clausify(ex : Expr) : Option[Expr] = ex match {
       case ie @ IfExpr(cond, then, elze) => {
-        val switch = FreshIdentifier("path", true).setType(BooleanType).toVariable
+        val switchId = FreshIdentifier("path", true).setType(BooleanType)
+        val switch = switchId.toVariable
         val placeHolder = FreshIdentifier("iteval", true).setType(ie.getType).toVariable
         newClauses = Iff(switch, cond) :: newClauses
         newClauses = Implies(switch, Equals(placeHolder, then)) :: newClauses
         newClauses = Implies(Not(switch), Equals(placeHolder, elze)) :: newClauses
         // newBools = newBools + switch.id
         ite2Bools = ite2Bools + (placeHolder.id -> switch.id)
+
+        if(!functionCallsOf(then).isEmpty)
+          guards ::= (switchId -> true)
+        if(!functionCallsOf(elze).isEmpty)
+          guards ::= (switchId -> false)
+
         Some(placeHolder)
       }
       case _ => None
@@ -916,7 +924,7 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
 
     val cleanedUp = searchAndReplaceDFS(clausify)(formula)
 
-    (cleanedUp, newClauses.reverse, ite2Bools)
+    (cleanedUp, newClauses.reverse, ite2Bools, guards.toSeq)
   }
 
   protected[leon] var exprToZ3Id : Map[Expr,Z3AST] = Map.empty
@@ -1340,13 +1348,13 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
       }
     }
 
-    private def treatFunctionInvocationSet(sVar : Identifier, pol : Boolean, fis : Set[FunctionInvocation]) : (Seq[Expr],Seq[(Identifier,Boolean)]) = {
+    private def treatFunctionInvocationSet(sVar : Identifier, pol : Boolean, fis : Set[FunctionInvocation], initialUnroll: Boolean) : (Seq[Expr],Seq[(Identifier,Boolean)]) = {
       val allBlocks : MutableSet[(Identifier,Boolean)] = MutableSet.empty
       var allNewExprs : Seq[Expr] = Seq.empty
 
       for(fi <- fis) {
         val temp = FunctionTemplate.mkTemplate(fi.funDef)
-        val (newExprs,newBlocks) = temp.instantiate(sVar, pol, fi.args)
+        val (newExprs,newBlocks) = temp.instantiate(sVar, pol, fi.args, initialUnroll)
 
         for(((i,p),fis) <- newBlocks) {
           if(registerBlocked(i,p,fis)) {
@@ -1362,15 +1370,23 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
     // Wouldn't it be better/more uniform to pretend the initial formula is a
     // function and generate a template for it?
     def initialUnrolling(formula : Expr) : (Seq[Expr], Seq[(Identifier,Boolean)]) = {
+      //val (cleanedFormula, clauses, _, guards) = clausifyITE(formula)
+      //val seqClauses = (cleanedFormula :: clauses).toSeq
+      //(seqClauses, guards)
+      //val funDef = new FunDef(FreshIdentifier("foo"), formula.getType, Seq())
+      //funDef.body = Some(formula)
+      //val startingVar : Identifier = FreshIdentifier("start", true).setType(BooleanType)
+      //val result = treatFunctionInvocationSet(startingVar, true, Set(FunctionInvocation(funDef, Seq())))
+      //(Variable(startingVar) +: result._1, result._2)
       val fi = functionCallsOf(formula)
       if(fi.isEmpty) {
         (Seq(formula), Seq.empty)
       } else {
         val startingVar : Identifier = FreshIdentifier("start", true).setType(BooleanType)
 
-        val result = treatFunctionInvocationSet(startingVar, true, functionCallsOf(formula))
-        //reporter.info(result)
-        (Variable(startingVar) +: formula +: result._1, result._2)
+        val result = treatFunctionInvocationSet(startingVar, true, functionCallsOf(formula), true)
+        val (clauses, guards) = initialUnrolling0(startingVar, formula)
+        (clauses ++ result._1, guards ++ result._2)
       }
     }
 
@@ -1380,8 +1396,78 @@ class FairZ3Solver(reporter: Reporter) extends Solver(reporter) with AbstractZ3S
       } else {
         val copy = blockMap((id,pol))
         blockMap((id,pol)) = Set.empty
-        treatFunctionInvocationSet(id, pol, copy)
+        treatFunctionInvocationSet(id, pol, copy, false)
+      }
+    }
+
+    def initialUnrolling0(startingVar: Identifier, formula: Expr): (Seq[Expr], Seq[(Identifier,Boolean)]) = {
+
+      var guardedExprs : Map[(Identifier,Boolean),Seq[Expr]] = Map.empty
+      def storeGuarded(guardVar : Identifier, guardPol : Boolean, expr : Expr) : Unit = {
+        assert(expr.getType == BooleanType)
+        val p : (Identifier,Boolean) = (guardVar,guardPol)
+        if(guardedExprs.isDefinedAt(p)) {
+          val prev : Seq[Expr] = guardedExprs(p)
+          guardedExprs += (p -> (expr +: prev))
+        } else {
+          guardedExprs += (p -> Seq(expr))
+        }
+      }
+  
+      def rec(pathVar : Identifier, pathPol : Boolean, expr : Expr) : Expr = {
+        expr match {
+          case l : Let => sys.error("Let's should have been eliminated.")
+          case m : MatchExpr => sys.error("MatchExpr's should have been eliminated.")
+  
+          case i @ IfExpr(cond, then, elze) => {
+            if(!containsFunctionCalls(cond) && !containsFunctionCalls(then) && !containsFunctionCalls(elze)) {
+              i
+            } else {
+              val newBool : Identifier = FreshIdentifier("b", true).setType(BooleanType)
+              val newExpr : Identifier = FreshIdentifier("e", true).setType(i.getType)
+              
+              val crec = rec(pathVar, pathPol, cond)
+              val trec = rec(newBool, true, then)
+              val erec = rec(newBool, false, elze)
+  
+              storeGuarded(pathVar, pathPol, Iff(Variable(newBool), crec))
+              storeGuarded(newBool, true,  Equals(Variable(newExpr), trec))
+              storeGuarded(newBool, false, Equals(Variable(newExpr), erec))
+              Variable(newExpr)
+            }
+          }
+  
+          case n @ NAryOperator(as, r) => r(as.map(a => rec(pathVar, pathPol, a))).setType(n.getType)
+          case b @ BinaryOperator(a1, a2, r) => r(rec(pathVar, pathPol, a1), rec(pathVar, pathPol, a2)).setType(b.getType)
+          case u @ UnaryOperator(a, r) => r(rec(pathVar, pathPol, a)).setType(u.getType)
+          case t : Terminal => t
+          case a : AnonymousFunction => {
+            Settings.reporter.warning("AnonymousFunction literal showed up in the construction of a FunctionTemplate.")
+            a
+          }
+        }
+      }
+      val newFormula = rec(startingVar, true, formula)
+
+      val asClauses : Seq[Expr] = {
+        (for(((b,p),es) <- guardedExprs; e <- es) yield {
+          Implies(if(!p) Not(Variable(b)) else Variable(b), e)
+        }).toSeq
       }
+
+      val blockers : Map[(Identifier,Boolean),Set[FunctionInvocation]] = {
+        Map((for((p, es) <- guardedExprs) yield {
+          val calls = es.foldLeft(Set.empty[FunctionInvocation])((s,e) => s ++ functionCallsOf(e))
+          if(calls.isEmpty) {
+            None
+          } else {
+            Some((p, calls))
+          }
+        }).flatten.toSeq : _*)
+      }
+
+      (Variable(startingVar) +: (newFormula +: asClauses), blockers.keys.toSeq)
+
     }
   }
 }
diff --git a/src/main/scala/leon/FunctionTemplate.scala b/src/main/scala/leon/FunctionTemplate.scala
index be4189b4283b2d79eefd63c94726ea7f6d683000..85ad0c8a5e3f8005d00f7173bd262be8441f8185 100644
--- a/src/main/scala/leon/FunctionTemplate.scala
+++ b/src/main/scala/leon/FunctionTemplate.scala
@@ -37,7 +37,7 @@ class FunctionTemplate private(
   // Returns two things:
   //  - a set of clauses representing the computation of the function/post
   //  - a map indicating which boolean variables guard which (recursive) fun. invoc.
-  def instantiate(aVar : Identifier, aPol : Boolean, args : Seq[Expr]) : (Seq[Expr],Map[(Identifier,Boolean),Set[FunctionInvocation]]) = {
+  def instantiate(aVar : Identifier, aPol : Boolean, args : Seq[Expr], initialUnroll: Boolean = false) : (Seq[Expr],Map[(Identifier,Boolean),Set[FunctionInvocation]]) = {
     assert(args.size == funDef.args.size)
 
     val idSubstMap : Map[Identifier,Identifier] =