diff --git a/src/main/scala/leon/termination/ChainBuilder.scala b/src/main/scala/leon/termination/ChainBuilder.scala
index 0c6106127ce7187ff4dded02b18863fcd332677b..f2410fd82cac6a518740a575230172a246d14e21 100644
--- a/src/main/scala/leon/termination/ChainBuilder.scala
+++ b/src/main/scala/leon/termination/ChainBuilder.scala
@@ -156,7 +156,7 @@ trait ChainBuilder extends RelationBuilder { self: Strengthener with RelationCom
         if (!checker.program.callGraph.transitivelyCalls(fd, funDef)) {
           Set.empty[FunDef] -> Set.empty[Chain]
         } else if (fd == funDef) {
-          Set.empty[FunDef] -> Set(Chain(chain.reverse))
+          Set(fd) -> Set(Chain(chain.reverse))
         } else if (seen(fd)) {
           Set(fd) -> Set.empty[Chain]
         } else {
diff --git a/src/main/scala/leon/termination/ChainProcessor.scala b/src/main/scala/leon/termination/ChainProcessor.scala
index c5a8ccb69c870b16f91e1c1dcfa5cb933bc8138b..af50911bd46dfc0c3519ab885acd94416df57267 100644
--- a/src/main/scala/leon/termination/ChainProcessor.scala
+++ b/src/main/scala/leon/termination/ChainProcessor.scala
@@ -6,7 +6,7 @@ package termination
 import purescala.Expressions._
 import purescala.Common._
 import purescala.Definitions._
-import purescala.Constructors.tupleWrap
+import purescala.Constructors._
 
 class ChainProcessor(
     val checker: TerminationChecker,
@@ -33,40 +33,37 @@ class ChainProcessor(
       reporter.debug("-+> Multiple looping points, can't build chain proof")
       None
     } else {
+      val funDef = loopPoints.head
+      val chains = chainsMap(funDef)._2
 
-      def exprs(fd: FunDef): (Expr, Seq[(Seq[Expr], Expr)], Set[Chain]) = {
-        val fdChains = chainsMap(fd)._2
-
-        val e1 = tupleWrap(fd.params.map(_.toVariable))
-        val e2s = fdChains.toSeq.map { chain =>
-          val freshParams = chain.finalParams.map(arg => FreshIdentifier(arg.id.name, arg.id.getType, true))
-          (chain.loop(finalArgs = freshParams), tupleWrap(freshParams.map(_.toVariable)))
-        }
-
-        (e1, e2s, fdChains)
+      val e1 = tupleWrap(funDef.params.map(_.toVariable))
+      val e2s = chains.toSeq.map { chain =>
+        val freshParams = chain.finalParams.map(arg => FreshIdentifier(arg.id.name, arg.id.getType, true))
+        (chain.loop(finalArgs = freshParams), tupleWrap(freshParams.map(_.toVariable)))
       }
 
-      val funDefs = if (loopPoints.size == 1) Set(loopPoints.head) else problem.funSet
-
       reporter.debug("-+> Searching for structural size decrease")
 
-      val (se1, se2s, _) = exprs(funDefs.head)
-      val structuralFormulas = modules.structuralDecreasing(se1, se2s)
+      val structuralFormulas = modules.structuralDecreasing(e1, e2s)
       val structuralDecreasing = structuralFormulas.exists(formula => definitiveALL(formula))
 
       reporter.debug("-+> Searching for numerical converging")
 
-      // worth checking multiple funDefs as the endpoint discovery can be context sensitive
-      val numericDecreasing = funDefs.exists { fd =>
-        val (ne1, ne2s, fdChains) = exprs(fd)
-        val numericFormulas = modules.numericConverging(ne1, ne2s, fdChains)
-        numericFormulas.exists(formula => definitiveALL(formula))
-      }
+      val numericFormulas = modules.numericConverging(e1, e2s, chains)
+      val numericDecreasing = numericFormulas.exists(formula => definitiveALL(formula))
 
       if (structuralDecreasing || numericDecreasing)
         Some(problem.funDefs map Cleared)
-      else
-        None
+      else {
+        val chainsUnlooping = chains.flatMap(c1 => chains.flatMap(c2 => c1 compose c2)).forall {
+          chain => !definitiveSATwithModel(andJoin(chain.loop())).isDefined
+        }
+
+        if (chainsUnlooping) 
+          Some(problem.funDefs map Cleared)
+        else 
+          None
+      }
     }
   }
 }
diff --git a/src/main/scala/leon/termination/ProcessingPipeline.scala b/src/main/scala/leon/termination/ProcessingPipeline.scala
index d2bae17b326623178671a2fc7db26954e013057e..92a11c6452c88f49986cd9382cae9ed72f70619a 100644
--- a/src/main/scala/leon/termination/ProcessingPipeline.scala
+++ b/src/main/scala/leon/termination/ProcessingPipeline.scala
@@ -165,8 +165,8 @@ abstract class ProcessingPipeline(context: LeonContext, initProgram: Program) ex
     val components = SCC.scc(callGraph)
 
     for (fd <- funDefs -- components.toSet.flatten) clearedMap(fd) = "Non-recursive"
-
-    components.map(fds => Problem(fds.toSeq))
+    val newProblems = components.filter(fds => fds.forall { fd => !terminationMap.isDefinedAt(fd) })
+    newProblems.map(fds => Problem(fds.toSeq))
   }
 
   def verifyTermination(funDef: FunDef): Unit = {
diff --git a/src/test/resources/regression/termination/valid/NNF.scala b/src/test/resources/regression/termination/valid/NNF.scala
new file mode 100644
index 0000000000000000000000000000000000000000..455cef7ec5201fd17edee71059dc38c9d7afa3d8
--- /dev/null
+++ b/src/test/resources/regression/termination/valid/NNF.scala
@@ -0,0 +1,99 @@
+import leon.lang._
+import leon.annotation._
+
+object PropositionalLogic {
+
+  sealed abstract class Formula
+  case class And(lhs: Formula, rhs: Formula) extends Formula
+  case class Or(lhs: Formula, rhs: Formula) extends Formula
+  case class Implies(lhs: Formula, rhs: Formula) extends Formula
+  case class Not(f: Formula) extends Formula
+  case class Literal(id: BigInt) extends Formula
+
+  def simplify(f: Formula): Formula = (f match {
+    case And(lhs, rhs) => And(simplify(lhs), simplify(rhs))
+    case Or(lhs, rhs) => Or(simplify(lhs), simplify(rhs))
+    case Implies(lhs, rhs) => Or(Not(simplify(lhs)), simplify(rhs))
+    case Not(f) => Not(simplify(f))
+    case Literal(_) => f
+  }) ensuring(isSimplified(_))
+
+  def isSimplified(f: Formula): Boolean = f match {
+    case And(lhs, rhs) => isSimplified(lhs) && isSimplified(rhs)
+    case Or(lhs, rhs) => isSimplified(lhs) && isSimplified(rhs)
+    case Implies(_,_) => false
+    case Not(f) => isSimplified(f)
+    case Literal(_) => true
+  }
+
+  def nnf(formula: Formula): Formula = (formula match {
+    case And(lhs, rhs) => And(nnf(lhs), nnf(rhs))
+    case Or(lhs, rhs) => Or(nnf(lhs), nnf(rhs))
+    case Implies(lhs, rhs) => nnf(Or(Not(lhs), rhs))
+    case Not(And(lhs, rhs)) => Or(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Or(lhs, rhs)) => And(nnf(Not(lhs)), nnf(Not(rhs)))
+    case Not(Implies(lhs, rhs)) => And(nnf(lhs), nnf(Not(rhs)))
+    case Not(Not(f)) => nnf(f)
+    case Not(Literal(_)) => formula
+    case Literal(_) => formula
+  }) ensuring(isNNF(_))
+
+  def isNNF(f: Formula): Boolean = f match {
+    case And(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Or(lhs, rhs) => isNNF(lhs) && isNNF(rhs)
+    case Implies(lhs, rhs) => false
+    case Not(Literal(_)) => true
+    case Not(_) => false
+    case Literal(_) => true
+  }
+
+  def evalLit(id : BigInt) : Boolean = (id == 42) // could be any function
+  def eval(f: Formula) : Boolean = f match {
+    case And(lhs, rhs) => eval(lhs) && eval(rhs)
+    case Or(lhs, rhs) => eval(lhs) || eval(rhs)
+    case Implies(lhs, rhs) => !eval(lhs) || eval(rhs)
+    case Not(f) => !eval(f)
+    case Literal(id) => evalLit(id)
+  }
+
+  @induct
+  def simplifySemantics(f: Formula) : Boolean = {
+    eval(f) == eval(simplify(f))
+  } holds
+
+  // Note that matching is exhaustive due to precondition.
+  def vars(f: Formula): Set[BigInt] = {
+    require(isNNF(f))
+    f match {
+      case And(lhs, rhs) => vars(lhs) ++ vars(rhs)
+      case Or(lhs, rhs) => vars(lhs) ++ vars(rhs)
+      case Not(Literal(i)) => Set[BigInt](i)
+      case Literal(i) => Set[BigInt](i)
+    }
+  }
+
+  def fv(f : Formula) = { vars(nnf(f)) }
+
+  @induct
+  def wrongCommutative(f: Formula) : Boolean = {
+    nnf(simplify(f)) == simplify(nnf(f))
+  } holds
+
+  @induct
+  def simplifyPreservesNNF(f: Formula) : Boolean = {
+    require(isNNF(f))
+    isNNF(simplify(f))
+  } holds
+
+  @induct
+  def nnfIsStable(f: Formula) : Boolean = {
+    require(isNNF(f))
+    nnf(f) == f
+  } holds
+
+  @induct
+  def simplifyIsStable(f: Formula) : Boolean = {
+    require(isSimplified(f))
+    simplify(f) == f
+  } holds
+}