Termination and non-termination specification inference

Techniques for proving termination and non-termination of imperative programs are usually considered as orthogonal mechanisms. In this paper, we propose a novel mechanism that analyzes and proves both program termination and non-termination at the same time. We first introduce the concept of second-order termination constraints and accumulate a set of relational assumptions on them via a Hoare-style verification. We then solve these assumptions with case analysis to determine the (conditional) termination and non- termination scenarios expressed in some specification logic form. In contrast to current approaches, our technique can construct a summary of terminating and non-terminating behaviors for each method. This enables modularity and reuse for our termination and non-termination proving processes. We have tested our tool on sample programs from a recent termination competition, and compared favorably against state-of-the-art termination analyzers.


Introduction
For the last ten years, we have seen a fruitful line of research on proving termination [2-5, 7, 11-17, 19, 26, 29, 30, 34, 37-39] and non-termination [1,6,8,24,31,35,47] of imperative programs. Although these techniques for proving program termination and nontermination are often considered separately, a termination prover might deploy its own non-termination analysis mechanism to search for a feasible counterexample when a termination proof fails. TREX [25] is one of the first works to combine two different termination and non-termination proving techniques to alternatively assist each Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than the author(s) must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permissions from permissions@acm.org. other in a whole program analysis for non-recursive programs. Nevertheless, current techniques for proving non-termination are mostly standalone techniques to existing termination proving mechanisms.
To capture the termination and non-termination behaviors of each program, Le et al. [33] has recently proposed an integrated specification logic with three temporal predicates Term M, Loop and MayLoop, which denote, respectively, the scenarios for definite program termination (with a lexicographic ranking measure M made of a list of positive integers), definite non-termination (with an unreachable post-condition) and possible (unknown) non-termination. However, this framework currently requires temporal specifications to be given by programmers.
We propose in this paper a modular inference framework that can analyze both the termination and non-termination of each method in a program. This approach is novel in that it guides us to perform suitable case-splits on pre-conditions that lead to definite non-termination or definite termination, where possible. If a definite termination (or non-termination) case is not yet attained, we may perform a further case-split via an abductive inference [36] or decide to finish with a MayLoop classification to signify an unknown outcome. For each method, our inference mechanism incrementally constructs a summary of its termination, non-termination or unknown behaviors, so that it can be reused in the inference of the remaining methods higher-up in the calling hierarchy.
void foo (int x, int y) requires U pr (x, y) ensures U po (x, y); { if (x < 0) return; else foo(x + y, y); } To support termination and non-termination inference, we introduce unknown temporal pre-and post-predicates in our specification logic to capture termination or non-termination behaviors (that are to be resolved by our inference). For example, in Figure 1, the pair of unknown pre-predicate U pr (x, y) and post-predicate U po (x, y) in the specification of method foo denotes that the termination or non-termination status of foo is currently unknown. While the pre-predicate U pr (x, y) in the method's precondition guides the overall inference process with suitable case-splits, the post-predicate U po (x, y) in its postcondition is meant to capture the reachability or unreachability of the method's exits. This post-predicate will be strengthened to false in scenarios where foo is definitely nonterminating. Moreover, it can also be used to trivially determine base-case scenarios with immediate termination property. This combined use of unknown pre-and post-predicates is novel, since it allows us to modularly analyze each method (with the help of casesplits where needed) to obtain a comprehensive summary of the method's termination and non-termination characteristics.
Our main contribution lies in a single modular bi-abductive analysis that automatically infers sufficient preconditions respectively Permission to make digital or hard copies of all or part of this work for personal or classroom use is granted without fee provided that copies are not made or distributed for profit or commercial advantage and that copies bear this notice and the full citation on the first page. Copyrights for components of this work owned by others than ACM must be honored. Abstracting with credit is permitted. To copy otherwise, or republish, to post on servers or to redistribute to lists, requires prior specific permission and/or a fee. Request permissions from Permissions@acm.org. Copyright is held by the owner/author(s). Publication rights licensed to ACM. hpred ::= c(v) ≡ (∃u · ρ) spec ::= (Ψ Pre , Φ Post ) Ψ Pre ::= (∃u·(ρ∧θ)) Φ Post ::= (∃u·(ρ∧U po (v))) θ : ρ ::= κ ∧ π κ ::= emp | v →d(u) | c(v) | κ 1 * κ 2 π ::= b | a | π 1 ∧π 2 | ¬π | ∃v·π b ::= true | false | v | b 1 =b 2 a ::= e 1 =e 2 | e 1 <e 2 | v=null e ::= k | v | k×e | e 1 +e 2 | −e where emp denotes an empty heap; v →d(u) specifies a heap node of data type d; k is a constant; u, v are variables Figure 2. A Specification Language for termination and non-termination of each method in a program. The rest of this paper is organized as follows. Section 2 introduces the novel unknown pre/post predicates and illustrates their use for inferring termination and non-termination properties of the foo example. Section 3 summarizes the background on the termination and non-termination reasoning with the temporal predicates. Section 4 shows how to generate a set of relational assumptions over the unknown temporal predicates. Section 5 introduces the inference algorithm to resolve the unknown predicates from their relational assumptions. Section 6 provides the experimental results. Section 7 discusses related work and Section 8 concludes our paper.

Overview of Our Approach
Specification Language. Le et al. [33] proposed three temporal predicates, Term M, Loop and MayLoop, to help reason about program termination and non-termination. For the current evaluation, we adopt these predicates as well as a rich underlying specification language proposed by [9] that is able to express both heap properties with separation logic (κ in Figure 2) and pure (non-heap) properties with Presburger arithmetic (π in Figure 2). This logic uses a fragment of separation logic with the separation conjunction * to denote the disjointness of heap portions and the heap predicate hpred ( Figure 2) to specify various data structures. Moreover, to simplify the presentation, we express a specification as a pair of preand post-condition (see spec in Figure 2). In our example programs, specifications will be written using the usual requires...ensures... form for better readability. Specifically for termination reasoning, we have designed the termination measure M as a (finite) list of arithmetic expressions [e] whose order is based on the lexicographic ordering <l ( defined below) and e:es denotes a non-empty list with e and es as its head and tail, respectively.
[] <l e: (e1 < e2) ∨ (e1 = e2 ∧ es1 <l es2) e1:es1 <l e2:es2 To facilitate termination and non-termination inference, we allow the use of an unknown temporal pre-predicate U pr (v) and a post-predicate U po (v) in the specification language to indicate the unknown termination status of a program. The solutions of these unknown predicates would be then derived by the inference mechanism, as shown next. Note that the inferred result for each unknown pre-predicate U pr (v) will be of the form (π ∧ θ) with θ ranging over {Term [e], Loop, MayLoop}; while the inferred result for each unknown post-predicate U po (v) will be in a guarded conjunction (π ⇒ post) with post being true or false. Such a guarded form is equivalent to a disjunctive form (π ∧ post) when the set of guards are complete. These unknown temporal predicates are expressed in pure arithmetic domain. Heap-based properties in our logic are currently handled prior to termination analysis.
Illustrating Example. We now demonstrate how our inference mechanism derives the preconditions for termination and nontermination of method foo in Figure 1. Initially, the termination and non-termination behaviors of method foo are captured by a pair of unknown pre-predicate U pr (x, y) and unknown post-predicate U po (x, y). Like the other known temporal predicates for termination and non-termination reasoning, these unknown predicates are part of the specification logic's formulas and can therefore be reasoned in a similar way via Hoare-style verification. With the help of an enhanced entailment procedure, we shall prove that the precondition of each method call is always satisfied and the postcondition always holds at the end of the method body.
For example, the verification conditions (VCs) encountered by Hoare-style forward verification of method foo are: The first VC (c1) is obtained from the base-case scenario when the post-condition of the foo method is being proven. The second VC (c2) captures the proving of precondition for the recursive call, while the last VC (c3) captures the entailment proving of the postcondition of method foo in the recursive branch. These VCs capture the unknown termination behaviors of both the caller (i.e. denoted by the pair of predicates U pr (x, y) and U po (x, y)) and the callee (i.e. denoted by U pr (x , y ) and U po (x , y )).
For these unknown predicates, we attempt to derive the strongest possible post-predicate, where possible. As we intend to capture the unreachability of each post-predicate, the strongest post-predicate in our analysis is actually false. If our inference for falsity of postpredicates fails, we denote its possible reachability by true instead and then attempt to infer the weakest pre-predicate, where possible. The temporal pre-predicates are ordered by the following implication hierarchy MayLoop ⇒r Loop and MayLoop ⇒r Term [e]. Amongst them, MayLoop is considered as the strongest one, which is analogous to false in the domain of logical specification. The intuition is that MayLoop can be used to denote the termination property of any program though such a use would form a rather poor specification, which is similar to how false could be naively (and redundantly) used as the precondition for any program. On the other hand, the Loop and Term [e] predicates are incomparable since they denote disjoint classes of programs (i.e. definitely nonterminating vs. definitely terminating programs, respectively). Our inference thus attempts to discover the weaker Loop and Term [e] for its unknown pre-predicate, where possible.
From the earlier VCs, we infer three relational assumptions where unknown pre-predicate U pr (x , y ) is related inductively to an earlier pre-predicate U pr (x, y) (see (a 0 2 )), while unknown postpredicate U po (x, y) is either expressed in base-case form (see (a 0 1 )) or related inductively to an earlier occurrence of the post-predicate U po (x , y ) (see (a 0 3 )).
We derive inductive definitions for these unknown predicates, in order to give the best possible interpretations to their temporal predicates. In the case of post-predicate, we attempt to determine its reachability or unreachability, so that we can immediately decide on either (base-case scenario for) termination or (inductive-case scenario for) definite non-termination. From the relational assumption (a 0 1 ), we can immediately infer a base-case scenario x<0 where the foo method would terminate. The other two relational assumptions occur under a different scenario x≥0 which neither indicates definite termination nor definite non-termination. From these partial instantiations on the two unknown temporal predicates, we refine them to the following definitions: where two auxiliary unknown predicates are introduced for the input scenario x≥0. Note that Term, short for Term [ ], is used to denote base-case termination scenario where its lexicographic ranking measure is trivially empty. Our unknown pre-predicate is being expressed as a disjunction on either known or unknown temporal resource constraints, while the post-predicate is being expressed as a guarded conjunction of either reachability (true), unreachability (false) or unknown. That is the two predicates are currently known for the input scenario x<0 but unknown for the scenario x≥0.
As the precondition is now partially known, we could refine each (a 0 i ) through a substitution with the partial definition of U pr (x, y) and U po (x, y) to get the new relational assumptions over the unknowns: The relational assumption (a 0 2a ) describes the reachability of the base-case condition (i.e. x <0), denoted by Term, under the input scenario x≥0. We can thus attempt a termination proof by synthesizing a ranking function for x≥0 but this proof fails. We then try a non-termination proof by examining (a 0 3a ) on unknown postpredicate to determine a condition for unreachability. Such condition must ensure that the base case is not reached in the next recursion, i.e. x ≥0, and we refer to this as potential non-termination precondition. Since x =x+y, the condition x+y≥0 would be a trivial potential non-termination pre-condition. However, our inference engine would discover a better (or weaker) condition, namely y≥0, for definite non-termination with the help of abductive inference. With this, a case-split with the condition y≥0 and its negation y<0 is used to refine the definitions for U 1 pr (x, y) and U 1 po (x, y) into: Consequently, the following six specialized assumptions are derived from the earlier ones (a 0 2a ), (a 0 2b ) and (a 0 3 ).
The first three relational assumptions, (a 1 1 ) − (a 1 3 ), form a group which will be analyzed together for the given input scenario x≥0∧y≥0. The next three relational assumptions, (a 1 4 ) − (a 1 6 ), form another group for the input scenario x≥0∧y<0.
The first group of relational assumptions, (a 1 1 ) − (a 1 3 ), allows us to confirm a definite non-termination scenario, since we can use (a 1 3 ) to determine the unreachability of its post-predicate U 2 po (x, y). By using the hypothesis U 2 po (x, y)≡false for both occurrences of the post-predicate U 2 po (x, y) in (a 1 3 ), we can inductively determine the falsity (or unreachability) of U 2 po (x, y). Note our use of inductive reasoning here which assumes the hypothesis that U 2 po (x, y) is unreachable under pre-condition x≥0∧y≥0, in order to prove it.
The second group of relational assumptions, (a 1 4 ) − (a 1 6 ), suggests us to prove the method's termination under the precondition x≥0∧y<0 first, since its base case (captured by (a 1 4 )) is possibly reachable under this condition. This termination scenario is confirmed, once we have derived a lexicographic ranking measure [x] that is bounded and would moreover decrease with each recursive invocation for the pre-predicate U 3 pr (x, y) using (a 1 5 ). As a summary of our combined analyses, we have effectively derived the following definitions for the two unknown predicates: Note how the unknown temporal predicates U 2 pr (x, y) and U 2 po (x, y) are being resolved to be Loop and an unreachable false for input scenario y≥0, respectively. In contrast, the unknown predicates U 3 pr (x, y) and U 3 po (x, y) are being resolved to be Term [x] and a reachable true state for input scenario y<0, respectively.
Using the inferred predicate definitions, we can finally construct the following case-based specification ( [20]) which fully captures termination and non-termination behaviors for method foo.

Other Examples
Our termination and non-termination inference is completely automated. By allowing unknown temporal predicates into functional correctness specifications, our inference mechanism can freely leverage on prior infrastructures to (i) handle a wider class of programs, and to (ii) improve the accuracy of the inference results. Note that prior safety specifications for the analyzed methods might be manually given or be automatically derived by other inference mechanisms, but they are orthogonal to our current proposal. We list below some interesting examples to demonstrate how our inference mechanism works with programs that already have some safety specifications.

Nested Recursion.
For examples with nested recursion, such as the Ackermann function and the McCarthy 91 function in Figure  3, some knowledge on its output may be crucial for the inference of their termination and non-termination properties. Without any specification, our inference mechanism returns incomplete summaries on the terminating and non-terminating behaviors of these two functions. The result for the Ackermann function is: While the inference shows that this function is terminating when m=0 (base case) or non-terminating when m<0 ∨ n<0, it cannot prove the termination of the function under the input scenario m>0∧n≥0 since the value of the second argument in the last recursive call is unknown (or unbounded). However, with the stronger specification given in Figure 3(a), with an lower bound res ≥ n+1 on the function's returned value, denoted by res, our inference mechanism can replace MayLoop in scenario m>0∧n≥0 by Term [m, n] where [m, n] is a valid lexicographic ranking function. Similarly, without specification, the inference only shows that the McCarthy 91 function terminates in its base case when n>100. However, with the specification given in Figure 3(b), our inference can prove that the function terminates for all inputs.
else append(x.next, y); } Figure 4. Specification with Implementation for append method of two linked lists While our termination inference mechanism does not directly infer postconditions, it has been made to work with other automated postcondition inference sub-systems, such as [23,40]. Such postcondition inference sub-systems are orthogonal to our proposal, and can be leveraged to provide a more comprehensive solution for fully automated termination and non-termination inference.
Heap-Manipulating Programs. Our inference mechanism can be readily integrated into existing verification frameworks (such as [9], or even shape inference system [32]) that reason about safety properties of heap programs via separation logic [41]. Such an extension can be applied to help prove the termination and nontermination of heap-manipulating programs. Figure 4 shows the specification and implementation (for the verification) of the method append that concatenates two linked lists x and y. With the separation conjunction * and the points-to operator → of separation logic, the heap predicate lseg(root, q, n) represents a list segment from root to q with n elements. This predicate can then be used in the declarations of other predicates, such as cll(root, n) for circular lists. Using these two predicates, we can capture two safety specifications of append in Figure 4.
In the first scenario when the input x is a null-terminating list with size n, our inference mechanism is able to show that the method append always terminates with the ranking function [n]. In the second scenario where x is a circular linked list, our inference can show that append is definitely non-terminating, after confirming (by induction) that its postcondition can be strengthened to false. These examples highlight the modular nature of our non-termination and termination inference mechanism, which can be built on top of other inference mechanisms.

Technical Background
So far we have illustrated a unified specification logic with three known temporal predicates: Term [e], Loop and MayLoop. Semantically, these predicates can be defined using resource capacities (on lower and upper bounds) of execution length, i.e.
The resource predicate RC L, U specifies a resource capacity with a lower bound L and an upper bound U. It is satisfied by each program state whose resource capacity (l, u) is subsumed by (L, U), i.e. L≤l and u≤U. Note that the function f([e]) obtains a finite bound through an order-embedding of [e] into naturals.
Verification conditions involving these temporal predicates can be discharged by a resource consumption entailment t, that is used to account for (lower and upper bound) resources that are utilized by each code fragment. Such entailment can be used to analyze termination or non-termination property for some given method via resource reasoning. Given the temporal constraint θa associated with the current program state ρ and the temporal resource constraint θc (of some code fragment that must be executed), the entailment ρ ∧ θa t θc θr checks whether the execution resource required by constraint θc can be met by the execution resource of constraint θa or not. If it succeeds, the entailment will return the remaining execution resource that is denoted by residue θr.
In terms of the actual execution capacity, this consumption entailment can be formalized by the following rule: where two subtraction operators are designed to cater to an integer domain extended with the ∞ value (i.e. N ∞ ): These two operators are essentially integer subtraction operators, except that their results are never negative and such that ∞−L∞ = 0 and ∞−U∞ = ∞. They are formulated in this way to give the best (or largest) possible lower and upper bound values to denote the execution capacity of residue. In addition, the subtraction Ua −U Uc requires a check for upper bound execution capacity, namely ρ ⇒ Uc≤Ua. This check is important to ensure that resource consumption is within the specified upper bound, and will also ensure that the residue is a valid resource capacity. The resource implication operator ⇒r on execution capacity, used in the implication hierarchy of known temporal predicates, can be defined based on the following subsumption relation: From this definition, MayLoop is the strongest pre-predicate in the subsumption hierarchy since it has the maximum execution capacity (0, ∞). It can subsume either Loop (with execution capacity (∞, ∞)) or Term [e] (with execution capacity (0, f([e]))) predicates. Note that the implication operator ⇒r is only weakly related to the resource consumption entailment operator, t, as follows: (θa ⇒r θc) ⇒ ∃θr · θa t θc θr For termination and non-termination inference, we have introduced unknown predicates U pr (v) for precondition and U po (v) for postcondition for each method, with U pr (v) denoting some execution capacity, and U po (v) specifying reachability of a method with a set of formal parameters v. To support its inference, we will have to extend the resource entailment procedure to handle entailments between known and unknown temporal constraints.
The most general form of temporal entailment is ρ∧ i U i po (vi)∧ θa t θc (θr, R), where each U i po (vi) is an unknown postpredicate accumulated into the program state after a recursive method call. The temporal constraint θa in the antecedent of the entailment might be an unknown pre-predicate U pr (v) or a known temporal predicate. The temporal constraint θc can be either an unknown post-predicate U po (v) or a known predicate. The residue Prog ::= tdecl meth tdecl ::= data c { field } field ::= t v t ::= c | bool | int | void meth : if v then e 1 else e 2 | return v where c is a data type name; mn is a method name; k is a primitive constant; f is a field name; v is a variable Figure 5. A Core Imperative Language constraint θr denotes the residual capacity after entailment. Each relational assumption R for the unknown temporal predicates is a pre-requisite to ensure the validity of the entailment when either θa or θc is unknown. It is defined as below.
can be defined as follows: This temporal entailment can be integrated into an entailment system with frame Ψ Φ ; Ψr, to obtain a new entailment procedure of the form Ψ Φ ; (Ψr, S), that also captures in its residue the set of relational assumptions S generated by the temporal sub-entailments. The rules to discharge entailments of logic formulas with disjunctions are:

Generating Temporal Assumptions
In this section, we show how our new entailment procedure is incorporated into Hoare logic to generate a set of relation assumptions over the unknown temporal constraints.
Language. To formalize this task, we provide a core language ( Figure 5) with usual constructs, such as data structure declaration tdecl , method declaration meth, method call, assignment. This core language does not include the while-loop construct, as it assumes an automatic translation of loops into tail-recursive methods. For int type, we assume the use of arbitrary precision integers. A method declaration consists of a specification with pre-and post-condition and its body. Primitive/library methods do not have a body and must have their specifications (including termination) pre-declared. For termination and non-termination inference, a pair of unknown pre-and post-predicate are automatically added into the specification of each method whose termination status is unknown.
Hoare rules. To support inference, Hoare judgment is formalized as {ΨPre} e {ΦPost, S}, where S is a generated set of temporal assumptions. For illustration, we show the rule for method call: To facilitate the termination inference, at method calls, we collect only nontrivial assumptions of unknown temporal constraints. We Initial defns for unknown pre/post predicates  3: for each mn i in M do 4: S ← spec_relass(S, Θ); T ← spec_relass(T , Θ) 8: G ← reach_graph(S) // Reachability graph for unknown pre-predicates 9: for each scc in G do 10: (r, Θ) ← TNT_analysis(G, scc, T , Θ) 11: if ¬r ∧ iter < MAX_ITER then iter++; goto 7 12: if iter ≥ MAX_ITER then break 13: T ← spec_relass(T , Θ) 14: G ← graph_update(G, Θ) 15: return finalize(Θ) Figure 6. Overall Inference Algorithm list below trivial relational assumptions, which will be removed by the function filter as shown in the rule [TNT−CALL]. Firstly, the relational assumption ρ∧θa ⇒ θc is trivial for any θa and θc if the context ρ is unsatisfiable. Secondly, the assumptions ρ∧Loop ⇒ θc and ρ∧MayLoop ⇒ θc are trivially valid for any program state ρ because the constraints Loop and MayLoop can accept any temporal constraints in the RHS [33]. Finally, ρ∧θa ⇒ Term M is trivial if the callee n, whose termination is denoted by the temporal constraint Term M, and the caller m are not mutually recursive.
Note that assumptions of the form ρ∧U 1 pr (v1) ⇒ U 2 pr (v2) are not trivial for any caller m and callee n. However, when m and n are in two different scc groups, this kind of assumptions can be avoided if we do a bottom-up verification and inference in which the (non-)termination of the callee n is inferred and the unknown U 2 pr (v2) is instantiated before the caller m is processed.
For each method declaration, we collect a set of relational assumptions S during the verification of its body, and another set of relational assumptions T at the method's exit points via the entailment for proving the post-condition, as shown below: The termination and non-termination inference engine is invoked when a whole group of mutually recursive methods are verified and their sets of relational assumptions are collected, as shown in the rule [TNT−INF] below.
The solve procedure infers definitions for unknown temporal predicates and will be depicted in detail next.

Inferring Termination and Non-Termination
This section is devoted to the solve procedure used to infer the definitions for the unknown pre/post-predicates, based on the set of relational assumptions generated by Hoare-style verification. The overall algorithm is shown in Figure 6. In this algorithm, Θ is used to store the set of definitions inferred thus far for the unknown temporal predicates. Since a key idea of our inference mechanism is case analysis that incrementally separates the terminating and non-terminating behaviors of the analyzed methods, the definition for each unknown predicate might be split into multiple scenarios, for which termination is either known or unknown.
The initial form of each unknown predicate is the predicate itself with guard condition true, e.g. U pr (v) ≡ true∧U pr (v). At the end of the analysis, all θ i pr and θ i po become known. The inference deals with two groups of temporal relational assumptions collected by rule [TNT−METH], namely 1. Pre-assumptions S collected when proving preconditions at method calls. They can be used to infer (i) ranking functions for termination proving, and (ii) temporal reachability graph that guides our search for proving termination vs. non-termination.
2. Post-assumptions T collected when proving postconditions contain information about unknown post-predicates. They can be used to infer (i) termination base cases, (ii) inductive unreachability to prove non-termination or (iii) new conditions for the case analysis.
The algorithm in Figure 6 first derives the base case of each analyzed method (line 4), and then refines the definitions of unknown temporal predicates in Θ with these newly inferred cases (line 5). After updating the set of relational assumptions (line 7), our algorithm (re-)builds the temporal reachability graph G from the latest S (line 8).
For each scc of the graph G in the bottom-up topological order, the analysis attempts to prove either termination or non-termination or to infer new cases for case-splitting and then updates the set Θ with the inferred result (line 10). If every unknown temporal predicate corresponding to the current scc is resolved into known predicates, the inference continues with the next sccs after updating the post-assumptions in T (line 13) and the graph G (line 14) with the new inferred known predicates. Otherwise, it restarts the core algorithm (line 11) with the updated Θ, whose elements have been refined into new sub-cases.
The algorithm halts when every unknown predicate has been resolved or the number of iterations reaches the maximum MAX_ITER pre-set by users. In the latter case, the remaining unknown predicates in Θ will be marked as MayLoop by an auxiliary procedure finalize. Next we will explain each inference step in some detail.

Inferring Base Case Termination
Identifying the conditions for base-case termination is an important first step before any other analyses. Formally: DEFINITION 3 (Base Case Pre-Condition). Each base case termination precondition of a method must satisfy the following three conditions: (i) Its method's exit is reachable from it. (ii) No mutually recursive method call is met in executions starting from this pre-condition. (iii) All other method calls encountered from this pre-condition must have been proven to terminate.
While a syntactic-based approach that identifies base-case termination from its control-flow may be sufficient, we propose a semantics-based approach which infers a method's base case precondition from the two sets of assumptions S and T collected from the method, as follows: Each post-assumption βj∧true ⇒ U po (v) ∈ T , whose antecedent does not contain any unknown post-predicate, capture a potential base-case termination condition. Due to over-approximation, the actual base-case condition (over the method's parameters v) must be formed by such conditions ( β j ), conjoined with the negation of contexts (¬ρ) for the recursive calls. By identifying the base-case condition in {a 0 1 } and conditions for recursive pre-assumption in {a 0 2 }, we can precisely infer syn_base(S, T ) = x<0∧¬(x≥0).
With the inferred base case β = syn_base(S, T ) (line 4), we can now invoke the procedure refine_base (line 5) to refine (or specialize) the unknown predicates U pr (v) and U po (v), before updating their definitions in Θ (via the operator ⊕) as shown below.
Since the method's termination status in the remaining condition µ = ¬β is unknown. In the new definitions of U pr (v) and U po (v), each pair of fresh predicates U i pr (v) and U i po (v) is associated with a disjunct µi in the disjunctive normal form of µ. For our running example, this refinement leads to: After the unknown predicates have been updated with base-case termination conditions, we transform the sets of relation assumptions by using the procedure spec_relass (line 7) described next.

Specializing Relational Assumptions
Whenever some unknown predicates in Θ receive new definitions, our inference algorithm will update its sets of relational assumptions with the procedure spec_relass. Its first parameter is a set of relational assumptions. Its second parameter Θ contains the definitions of unknown predicates.
For each relational assumption with unknown predicates, the procedure spec_relass finds the current definitions of these unknown predicates in Θ and substitutes them directly into the assumption. As the definition of each unknown predicate consists of exclusive and complete guards, we can further split each substituted assumptions into multiple specialized assumptions. We show below just one example where spec_relass is called with a new pre-assumption with two unknown predicates.

Resolving Temporal Reachability Graph
The core of our inference algorithm (in Figure 6) incrementally resolves the unknown predicates present in the (specialized) relational pre-assumptions. If its attempt fails, it would also derive conditions for the next case analysis. This core algorithm uses a reachability graph G, constructed from pre-predicates in S, to guide its proof search. Formally: DEFINITION 4 (Temporal Reachability Graph). Given a set of preassumptions S, a temporal reachability graph G = (V, E) is constructed from a set of vertices V and a set of labeled edges E, as follows. For each pre-assumption ρ∧θa ⇒ θc ∈ S, we add two vertices θa and θc into V and an edge (θa, ρ, θc) from θa to θc labeled by ρ into E.
For example, the two graphs G1 and G2 are built for the inference of the running example. G1 is constructed from pre-assumptions (a 0 2a ) and (a 0 2b ) obtained after base case inference. The edges of G1 are labeled by ρ(a 0 2a ) and ρ(a 0 2b ), the contexts in (a 0 2a ) and (a 0 2b ) resp., e.g. ρ(a 0 2b ) ≡ (x≥0∧x =x+y∧y =y∧x ≥0). The self-loop edge on node U 1 pr denotes the case when the latest values of program variables (i.e. x ≥0), are still in the same loop condition as their initial values (x≥0). The edge from U 1 pr to Term indicates the base case is reached when x <0. Similarly, the graph G2 is constructed from pre-assumptions (a 1 4 ), (a 1 5 ) and (a 1 2 ) after a new case split y≥0 and y<0 has been inferred.
Our core algorithm firstly partitions G into strongly connected components (scc), (e.g. dashed boxes in G1 and G2), whereby each unknown temporal predicate denotes an unknown behavior. Moreover, this unknown predicate is mutually dependent on the other predicates in the same scc. Using a bottom-up approach, the inference mechanism processes each scc in a topologically sorted order. With this approach, termination and non-termination proofs for phase-change programs [14] and that for mutual recursion are easily supported.  Our core algorithm, named TNT_analysis, for manipulating each scc is outlined in Figure 7. After this analysis, if all vertices in the scc are resolved as known temporal predicates, our procedure returns the result r=true. Otherwise, it returns r=false to allow inference mechanism to restart for the next iteration (from line 7 in Figure 6). Moreover, upon termination of this procedure, some unknown pre-and post-predicates in store Θ, are updated with their new definitions.
Our procedure (Figure 7) uses the set O of the scc's successors to determine whether termination proof (by sub-procedure prove_Term), or non-termination proof (by prove_NonTerm), should be applied to resolve the unknown temporal predicates. Specifically, when the scc has only one unknown node U pr without any cyclic edge and successor (line 20), we resolve the unknown pre-predicate U pr ≡ Term and its corresponding post-predicate U po ≡ true for trivial termination (line 22). Moreover, when the set O is nonempty, the procedure invokes prove_Term with ranking function synthesis only if every element of O is a known Term [e] predicate (line [24][25].
For the running example, the procedure applies termination proofs for the left scc in G1 and the middle scc in G2. For the left scc in G2, it applies a non-termination proof directly. In the next sub-sections, we present the sub-procedures for proving termination and non-termination over a scc.

Inferring Ranking Function
For proving termination on a scc, we implement the procedure prove_Term (sketched in Figure 8) to find a linear ranking function for each unknown pre-predicate in this scc by using a constraintbased technique [22,23,38,42] with Farkas' lemma [43].
Initially, we create a unique ranking function template for each unknown pre-predicate U pr (v1, .., vn) ∈ scc by the procedure gen_rank, defined as where c0, c1, . . . , cn are unknown coefficients of the ranking function. Next, we generate a set of constraints over these ranking functions from every edge in G that connects two nodes in the scc (line 30). That is, given an edge e ≡ (U i pr (vi), ρ, U j pr (vj)) ∈ G(E) s.t. U i pr (vi), U j pr (vj) ∈ scc, the constraint generated from it is This constraint indicates that the ranking function ri(vi) is bounded and decreasing across a (mutually) recursive method call under the call context ρ. For example, the constraint generated from the middle scc in G2 is ∀x, y · x≥0∧x =x+y∧y =y∧x ≥0∧y<0 ⇒ r(x, y)>r(x , y ) ∧ r(x, y)≥0 which is then solved by syn_rank to obtain the ranking function r(x, y) = x. The method syn_rank (line 31) solves the generated constraints by applying Farkas' lemma on them to obtain another set of constraints over their unknown coefficients, which can be solved by a nonlinear solver, such as [28], to get the actual values of these 36: procedure prove_NonTerm(scc, T , Θ) 37: for each U i pr ∈ scc do 38: return (r, Θ ⊕ D) Figure 9. Proc. for Proving Non-Termination over a scc unknowns. The result is a substitution Γ which maps each unknown coefficient to its actual value. If the ranking function synthesis succeeds, we update each unknown pre-predicate in this scc into Term with an actual ranking function (line 34 in Figure 8). Otherwise, we prove nontermination on this scc (line 26 in Figure 7). The ranking function for a pre-predicate can be obtained by applying the substitution Γ to its ranking function template, as shown below. Note that We also support the synthesis of lexicographic ranking functions, details are omitted for simplicity of presentation.
These post-assumptions capture possible non-termination of its method due to predicate U po (v) being unknown, under the condition ρ ∧ µ where the context ρ is satisfiable. The first post-assumption describes a base-case scenario. In order to ensure unreachability of its post-predicate, we must check that ρ ∧ µ is unsatisfiable. The second post-assumption shows that we can meet a non-terminating method call (with the postcondition false) if the condition ηi is satisfied by ρ∧µ. In addition, we can meet a (mutually) recursive call whose termination is unknown if µj is satisfied, and thus the respective pre-predicate of U j po (vj) also belongs to the analyzed scc. We call the conditions ηi, µj and µ potential non-termination conditions as they could lead to an actual non-termination.
By induction, we prove that a caller is definitely non-terminating under a condition µ, assuming that one of its callee is definitely non-terminating under the same condition. Given a set of postassumptions Ts, we prove that if each unknown post-predicate in their LHS is false then every unknown post-predicate in their RHS is also false. This is done by the procedure abd_inf (line 39).
If the proof succeeds for all pre-predicates in scc (signified by r in line 40), we mark the unknown termination status as definitely non-terminating. This procedure thus refines, where possible, each unknown pre-predicate as U pr (v) ≡ Loop and its post-predicate as U po (v) ≡ false (line 41) and updates Θ before returning (true, Θ).
For our running example, (a 0 1 ) and (a 0 3 ) from T would cause prove_NonTerm(scc, T , Θ) to return false, but provide an abductive condition y≥0 that facilitates case-splitting (see next subsection). In contrast, (a 1 3 ) would be used to show that U 2 po (x, y) is inductively false (or unreachable).

Case-Splitting
If non-termination proving fails, the method abd_inf abductively infers new sub-conditions from the failed proof to refine the potential non-termination condition by case-split.
For each condition β k , the solution α k ≡ β k is a trivial but the weakest solution for α k . For a more effective case-split, we aim to derive a stronger abductive condition α k . By the same constraintbased approach used for the ranking function synthesis, we as- ., vn≡v and c 0 , .., cn are unknown coefficients. We might solve these unknown coefficients with additional optimal constraints, e.g. the number of zero-coefficients is maximum, so that we can obtain a better solution with minimum number of program variables.
Given a set of collective abductive conditions C, the procedure subst_unk (line 42) refines the pair of (U pr (v), U po (v)) with these new sub-cases for the update of Θ.
As the conditions in C might be overlapping, we use the function split defined below to partition these conditions into the new set of mutually exclusive conditions {µj} m j=1 such that C ≡ {µj}. We also add into the new set the condition µm+1 = ¬µ1∧. . .∧¬µm, if it is satisfiable, to cover the missing case, so that {µj} m+1 j=1 is complete. Note split({}) = {}.

Experiments
We have implemented the proposed inference mechanism on top of HIPTNT [33], an existing verification system that can verify both termination and non-termination specifications given by users. The new inference system HIPTNT+ and this paper's artifact are available for both online use and download at http://loris-7.ddns.comp.nus.edu.sg/~project/hiptnt/plus/. To evaluate our approach, we compare our tool against state-ofthe-art systems, i.e. T2 [7], ULTIMATE [26] and AProVE [21]. The last tool is the recent winner for several categories of problems in the annual Termination Competition 2014 (TermCOMP'14) [46] and the Termination category in the Competition on Software Verification 2015 (SV-COMP'15) [45]. We made our preliminary comparison based on a set of numerical and pointer-based C programs selected from four benchmarks used for the Termination category of the SV-COMP'15. These benchmarks were largely contributed by the teams of AProVE and ULTIMATE. We have excluded 61 programs with arrays and strings from the total 399 programs in 4 benchmarks, since these two aspects 1 have not yet been handled by our specification inference and verification system. In addition, we made a comparison with T2 for only 221 loopbased integer programs from the first 3 benchmarks because the tool llvm2KITTeL [18] (which translates C programs into T2's format) cannot properly handle pointers and recursive methods. For AProVE and ULTIMATE, we used their SV-COMP'15 versions, which are described in [44] and [27], respectively. The experiments were performed on an Ubuntu 12.04 machine with the AMD Opteron 6172 (2.1GHz) processor and 64GB of RAM.
In Figure 10 and 11, we report the number of programs whose main methods' termination or non-termination were proven successfully in columns labeled by Y (for termination) or N (for nontermination), respectively. The columns U (i.e. unknown) show the number of programs in which the tools cannot decide whether they are definitely terminating or non-terminating. The number of unsuccessful cases in which the tools give no answer after a timeout is provided in the columns T/O. As in the TermCOMP'14 competition, we set a wall-clock timeout of 300 seconds for the proving process on each program. Finally, the last column in each benchmark presents the total time (excluding timeouts) each tool took to prove the termination and non-termination of the whole benchmark. In this evaluation, we only report the wall-clock time instead of the consumed CPU time of all the verifier's processes because CPU time of tools executing jobs in parallel, such as AProVE, would be much higher otherwise. Our tool's timing covers memory safety analysis and post-condition inference, where required.
The overall result shows that our HIPTNT+ can efficiently (without any timeout) infer more (non-)termination properties than the other tools. Note that all answers (specifications inferred) that were returned by our tool have been successfully re-verified 2 by an underlying automated verification system. Thus, our tool does not have any false positive nor negative for this set of benchmarks. For the other analyzers, we check their answers and found that T2 initially had five unsound outcomes which were subsequently fixed 3 .

Related Work
Over the last decade, there has been a large body of work on proving program termination. Most of these termination provers, such as TERMINATOR [12] and its successor T2 [7,16], ARMC [39], TAN [29] and ULTIMATE [26], either show that a program terminates for all (given) inputs or return a counterexample to termination upon the failure of termination proofs. However, due to the incompleteness of termination-based techniques, these provers cannot guarantee that every returned counterexample (from failed termination proofs) leads to a definitely non-terminating execution. Thus, each tool might deploy a separate non-termination proving technique to prove that the counterexample is feasible. Also, each such counterexample is only an under-approximation of its program execution, so that it does not capture the wider scenarios for non-terminating behaviors of the analyzed program.
We have also seen much related work on proving program nontermination, e.g. [1,6,8,24,31,35,47]. Non-termination provers, such as TNT [24] and INVEL [47], attempt to disprove program termination by searching for some initial configurations that act as witnesses for non-termination. To find a wider class of nontermination bugs, these approaches attempt to discover sufficient preconditions for non-termination. Nevertheless, since non-termination proving techniques are also incomplete, the analyzed program is not guaranteed to terminate under the complement of the inferred pre-condition for non-termination.
The dual problem of conditional termination, first addressed in [14], identifies initial configurations that ensure termination. In [14], such termination preconditions are derived from potential ranking functions, which are bounded but not decreasing. Later, the tools of FLATA [4] and ACABAR [19] infer the sufficient precondition for termination from (the negation on over-approximation of) the set of initial states from which the program might not terminate. However, FLATA differs from ACABAR by limiting itself to classes of loops with restricted forms in which the precise non-termination conditions are definable.

Conclusion
We have proposed a modular inference framework for program termination and non-termination. By incorporating unknown pre/postpredicates into specification logic for termination reasoning, our proposed framework employs a Hoare-style forward verification to collect a set of relational assumptions to help soundly discover termination and non-termination properties. Our technique analyzes program termination and non-termination at the same time, and constructs a summary of these behaviors for each method. This enables better modularity and reuse for our proving processes. Furthermore, it is integrated with a verification system allowing us to use partial specification and to re-check our inference outcome. As seen in the experiments over SV-COMP'15 benchmarks, our tool compares favorably against current state-of-the-art termination analyzers.
We shall now discuss two current limitations of our tool. Firstly, our tool handles non-deterministic inputs by identifying conditional statements that directly depend on non-deterministic values. Each such non-deterministic conditional is marked as non-terminating if either of its two branches is non-terminating. This works for most examples, but is less general than the proposal in [8]. Secondly, while we support lexicographic linear ranking functions (LLRF) in our termination reasoning, we cannot handle programs that critically depend on Ramsey's theorem [10,37] or those that are based on size-change principles [34] but do not have LLRF counterpart. It would be interesting to explore future extensions to our specification logic to better support non-determinism and these other kinds of termination proofs.