PEQcheck: Localized and Context-aware Checking of Functional Equivalence (Technical Report)
aa r X i v : . [ c s . L O ] J a n PEQcheck: Localized and Context-awareChecking of Functional Equivalence(Technical Report)
Marie-Christine Jakobs
Technical University of Darmstadt, Department of Computer Science,Darmstadt, Germany
Abstract.
A refactoring must preserve the program’s functionality. How-ever, not all refactorings are correct. Preservation of the functionalitymust be checked. Since programs are rarely formally specified, we usethe original program as functional specification and check whether theoriginal and refactored program are functionally equivalent . More con-cretely, our
PEQcheck technique follows a common approach and re-duces equivalence checking to program verification. To increase efficiency,
PEQcheck generates several verification tasks, namely one per refac-tored code segment and not one per function as typically done by priorwork. Additionally,
PEQcheck takes the context of the segments intoaccount. For example, only modified, live variables need to be equivalentand read-only variables can be shared between original and refactoredcode segments. We proved soundness of our
PEQcheck technique andimplemented it in a prototype tool. Our evaluation shows that the local-ized checking of
PEQcheck can indeed be beneficial.
Keywords:
Functional equivalence · Equivalence checking · FunctionalEquivalence Checking · Software Verification · Program Generation.
Refactoring [22,13] is applied to improve the software’s qualities. For example,execution hot spots can be parallelized to improve the software’s performance—the motivation for our work is code parallelization with OpenMP [25]. Whilea refactoring aims at improving the software’s quality, it simultaneously mustpreserve the software’s functionality. To avoid that a refactoring inadvertentlyalters the functionality, the refactored software must be verified.Different approaches exist to guarantee that a refactored program preservesthe functionality. For example, one could prove the correctness of the appliedrefactoring rules [14,39,19]. However, this does not work for arbitrary, manualrefactorings. A common technique used in industry is regression testing [44],but testing typically fails to examine all program behaviors and, thus, may missregressions. An alternative to testing is formal software verification [11]. Incre-mental and regression verification techniques [42,17,32,7,29,15] aim at efficient
M.-C. Jakobs re-verification of changed programs. Many of those techniques require a specifica-tion of the functional behavior, which often does not exist. In contrast, regressionverification techniques that check the functional equivalence of the original andrefactored software do not suffer from this problem.To show equivalence of two programs or functions, one can apply relationalprogram verification [5,43,4], use a (bi)simulation relation [46,33,10,9], transformthe programs into models and prove model equivalence [35,38,3,40,34], computesymbolic summaries and check if they are equivalent [28,2], convert the equiv-alence problem into a Horn constraint problem [12], or combine program gen-eration with verification [15,16,31,20,41,8,36,1]. The latter solution encodes theequivalence problem as a verification task, which is then verified by a standardverifier. This solution is particularly appealing because it does not require spe-cific proof techniques. Furthermore, it can directly profit from and easily switchbetween existing verification technologies.We are interested in checking equivalence of a sequential program and itsOpenMP parallelization. Our goal is to reduce equivalence checking to a programverification problem. Unfortunately, many existing approaches [15,16,31,20,41]focus on sequential programs and are unsound for parallel programs. For exam-ple, they assume that a function called with the same inputs (including globalvariables) returns the same result and, thus, replace function calls by uninter-preted functions. This assumption is, however, not necessarily true when anotherthread interferes with the function execution. While CIVL [36] and RVT [8] sup-port parallel programs, they perform equivalence checking on program or func-tion level. In order to reduce the state space that needs to be considered duringverification, we want to check equivalence on the level of (parallelized) codesegments. Among the approaches that reduce equivalence checking to programverification, only the approach of Abadi et al. [1] supports (parallelized) codesegments. However, their approach requires a bijection between inputs of thecode segments as well as between their outputs. Especially, a bijection betweeninputs is an unnecessarily strict assumption, which e.g., may prohibit the use ofstrategy patterns in only one of the code segments.In this paper, we present
PEQcheck , a sound approach that generates ver-ification tasks to check equivalence of code segments. While our motivation for
PEQcheck is to check the equivalence of pairs of a sequential and a parallelizedcode segment,
PEQcheck can also be used to check equivalence of sequentialcode segments as well as to check equivalence of parallel code segments.
PEQcheck uses dataflow analyses to determine the context of the codesegments, i.e., how variables are used in and after the code segments. This infor-mation allows
PEQcheck to develop a fine-grained differentiation of variables,which is used to reduce the complexity of the generated verification task. Forexample, non-modified variables are shared, inputs are only initialized equallywhen they are used before they are defined in the code segment, and equivalencechecking is limited to modified variables that are used after the code segments.Existing approaches partially consider some of these optimizations. For example,SymDiff [20] restricts equivalence checking to modified variables and RVT [15,16] ocalized and Context-aware Checking of Functional Equivalence 3
Listing 1.1.
Sequential program i nt sum2 par ( unsigned char N) { i nt j , sum ;sum = N; for ( j=N −
1; j > =0; j −− ) { sum += j ; } return sum + 2 ; } Listing 1.2.
Parallelized program i nt sum2 par ( unsigned char N) { i nt i , sum ;sum = 0 ; for ( i =1; i < = N; i ++) { sum += i ; } return sum + 2 ; } Listing 1.3.
Verification task i nt main ( ) { unsigned char N; i nt i , j , sum s , sum ;N = random uchar ( ) ;sum s = N; for ( j=N −
1; j > =0; j −− ) { sum s += j ; } sum = 0 ; for ( i =1; i < = N; i ++) { sum += i ; } a s s e r t ( sum s == sum ) ; return } Fig. 1.
Example sequential program, its parallelization, and the derived verificationtask for equivalence checking only initializes global variables that are written to by at least one of the pro-grams. However, to the best of our knowledge,
PEQcheck is the first regressionverification approach that uses such a fine-grained differentiation of variables.We proved soundness of our
PEQcheck approach. As a proof-of-concept, wealso implemented a prototype for
PEQcheck and applied it to several examples.Our evaluation shows that non-equivalence is detected and that focusing on codesegments in equivalence checking can be beneficial.
We demonstrate our
PEQcheck approach with the sequential and parallelizedprogram on the left-hand side of Fig. 1. Both programs compute the sum of thefirst N numbers plus 2. To show that the two functions are equivalent, we provethe equivalence of the two highlighted code segments. The resulting verificationtask is shown on the right-hand side of Fig. 1. We explain its construction next.First, we find out which variables are used in the code segments and how. Wewill use this information to determine which variables (1) can be shared, (2) needto be declared, (3) need to be equivalent, and (4) whether and how to initialize M.-C. Jakobs the variables. To this end, we identify the variables V used in the code segments,which of them are modified ( M ) in the code segment, which of them are used inthe code segment before they are defined ( UB ), and which are live after the codesegment ( L ). We get V seq = { j, N, sum } , V par = { i, N, sum } , M seq = { j, sum } , M par = { i, sum } , UB seq = UB par = { N } , and L seq = L par = { sum } .We use the variable names to relate the variables of the two segments. Thus,our approach fails if there exist variables with the same name, but differenttypes. Furthermore, we allow both code segments to use additional (input)variables, e.g., the parallelized code segment uses additional variable i .After we determined the different sets, we continue with the identification ofshared variables, which is important for code generation. Variables that are usedin both code segments (i.e., V seq ∩V par ) and are not modified can be safely shared.In contrast, modified variables that occur in both programs need to be duplicatedand the sequential code segment will use the duplicated variables instead. Thecode segments in our example share common variable N and variable sum needsto be duplicated. Here, we use sum s for the duplicated variable.Finally, we build the verification task. A verification task starts with thedeclaration of the variables, which is the union of V seq , V par , and the duplicatedvariables. For our example, we must declare variables { i, j, N, sum, sum s } . Afterthe declarations, variables are non-deterministically initialized whenever neces-sary. All variables that are used before they are defined by the code segment needto be initialized. Hence, we initialize all variables UB ∗ seq ∪ UB par , where UB ∗ seq is derived from UB seq by replacing duplicated variables by their duplicate. If avariable and its duplicate are initialized, the duplicate will be initialized with thesame value as the original variable. Our example verification task calls function random ushort to non-deterministically initialize variable N . Thereafter, it exe-cutes the sequential and parallelized code segment. The sequential segment usesthe duplicated variables where necessary. At last, the task checks the equivalenceof all shared, modified variables that may be live afterward, i.e., variables from( M seq ∪ M par ) ∩ ( L seq ∪ L par ). It uses one assert statement for each variable thatchecks the equivalence of the variable and its duplicate. Our example checks theequivalence of variables sum and sum s . For the sake of representation, we restrict ourselves to imperative programs oninteger variables and exclude synchronization primitives because we do not studysynchronization issues. The following grammar describes our programs. S := E | v := ℓ aexpr ; | assert ℓ bexpr ; | if ℓ bexpr then S else S | while ℓ bexpr do S | S ; S | [ S k . . . k S n ] Note that we can safely ignore variables that are only defined in the scope of thecode segment. They do not require declaration nor initialization. Neither can theybe accessed after the code segment. Providing the relation of the variables, one can overcome this problem. Our implementation supports C programs with OpenMP pragmas for parallelization.ocalized and Context-aware Checking of Functional Equivalence 5 ( v := ℓ aexpr ; ,σ ) v := aexpr ; −−−−−−→ ( E,σ [ v := σ ( aexpr )] σ ( bexpr )=true( assert ℓ bexpr ; ,σ ) bexpr −−−→ ( E,σ ) ( E ; S,σ ) nop −−→ ( S,σ ) σ ( bexpr )=true( if ℓ bexpr then S else S ,σ ) bexpr −−−→ ( S ,σ ) σ ( bexpr )=false( if ℓ bexpr then S else S ,σ ) ¬ bexpr −−−−→ ( S ,σ ) σ ( bexpr )=true( while ℓ bexpr do S,σ ) bexpr −−−→ ( S ; while ℓ bexpr do S,σ ) σ ( bexpr )=false( while ℓ bexpr do S,σ ) ¬ bexpr −−−−→ ( E,σ )( S ,σ ) op −→ ( S ′ ,σ ′ )( S ; S ,σ ) op −→ ( S ′ ; S ,σ ′ ) ( S i ,σ ) op −→ ( S ′ i ,σ ′ )([ S k ... k S i k ... k S n ] ,σ ) op −→ ([ S k ... k S ′ i k ... k S n ] ,σ ′ ) ([ E k ... k E ] ,σ ) nop −−→ ( E,σ ) Fig. 2.
Rules for operational semantics
We let E denote the empty program and expect that arithmetic expressions aexpr and boolean expressions bexpr are constructed by applying standard op-erators on integers. More complex programs S are composed of subprograms S i .To identify subprograms unambiguously, we associate each basic statement witha label ℓ that is unique in the program.The set V denotes all program variables and V ( S ) ⊆ V describes the variablesof (sub)program S , i.e., all variables that occur in an arithmetic or booleanexpression of S or on the left-hand side of an assignment in S . Similarly, subset V ( expr ) ⊆ V refers to the variables occurring in expression expr .To build proper verification tasks, PEQcheck needs to rename certain pro-gram variables. To this end, we use a bijective, renaming function ρ : V 7→ V and replace all occurrences of any variable v by ρ ( v ). The result is the renamedprogram R ( S, ρ ). Similarly, R ( expr, ρ ) denotes the renaming of expr . In Fig. 1,we apply the renaming function ρ sum2 to the sequential code segment, where ρ sum2 ( sum ) = sum s , ρ sum2 ( sum s ) = sum , and ρ sum2 ( v ) = v otherwise. Forthe program semantics, we rely on an operational semantics, which defines exe-cutions as transitions between execution states. An execution state is a pair ofa program plus a data state. A data state σ : V 7→ Z assigns to each variable aninteger value. We use Σ to denote the set of all data states and define ρ ( σ ) ∈ Σ such that for all v ∈ V : ρ ( σ )( v ) = σ ( ρ − ( v )). Furthermore, for any σ, σ ′ ∈ Σ and any subset V ⊆ V , we write σ = | V σ ′ if for all v ∈ V : σ ( v ) = σ ′ ( v ).An execution step is defined by the rules shown in Fig. 2. The state up-date σ [ v := σ ( aexpr )] returns a new data state σ ′ with σ ( w ) = σ ′ ( w ) for all w ∈ V with w = v and σ ′ ( v ) = σ ( aexpr ). Since we do not specify the expres-sion syntax, we also do not specify their evaluation. However, we require thatexpression evaluation is (a) deterministic, (b) only depends on the variablesused in the expression, i.e., ∀ σ, σ ′ ∈ Σ : σ = | V ( expr ) σ ′ = ⇒ σ ( expr ) = σ ′ ( expr ),and (c) is consistent with renaming, i.e., σ ( expr ) = ρ ( σ )( R ( expr, ρ )). In ad-dition, we assume that the evaluation of a variable is the look up of its valueand the equivalence of two variables checks that their values are identical, i.e., ∀ v, v ′ ∈ V : σ ( v == v ′ ) = ⇒ σ ( v ) = σ ( v ′ ). M.-C. Jakobs
Next, we inductively define the executions ex ( S ) of a program S . σ ∈ Σ ( S, σ ) ∈ ex ( S ) ( S , σ ) op −−→ . . . op n −−→ ( S n , σ n ) ∈ ex ( S ) , ( S n , σ n ) op n +1 −−−−→ ( S n +1 , σ n +1 )( S , σ ) op −−→ . . . op n −−→ ( S n , σ n ) op n +1 −−−−→ ( S n +1 , σ n +1 ) ∈ ex ( S ) We write (
S, σ ) → ∗ ( S ′ , σ ′ ) if we are not interested in the intermediate stepsof the execution. Furthermore, we say that ( S, σ ) → ∗ ( S ′ , σ ′ ) (i) terminatesnormally if S ′ = E and (ii) violates an assertion if S ′ violates an assertion in σ ′ . Aprogram S violates an assertion in state σ if (a) there exists S a = assert ℓ bexpr , σ ′ ( bexpr ) = f alse , and S = S a or S = S a ; S ′ or (b) S = [ S k . . . k S i k . . . k S n ] or S = [ S k . . . k S i k . . . k S n ]; S ′ and there exists S i that violates an assertion in σ .Analogous to executions, we define syntactic paths syn P ( S ) of a program S .In contrast to executions, syntactic paths ignore the data state. S ∈ syn P ( S ) S op −−→ . . . op n −−→ S n ∈ syn P ( S ) , ∃ σ, σ ′ ∈ Σ : ( S n , σ ) op n +1 −−−−→ ( S n +1 , σ ′ ) S op −−→ . . . op n −−→ S n op n +1 −−−−→ S n +1 ∈ syn P ( S )( S ) Again, we write S → ∗ S ′ if we are not interested in the intermediate steps.Based on the above semantics, we define when two (sub)programs are equiv-alent. We focus on partial equivalence , i.e., we restrict equivalence to executionsterminating normally. Also, we ignore intermediate variables and are only inter-ested in equivalence with respect to output variables, i.e., variables that containthe computation results. Given the set of output variables, two programs areequivalent if all executions of the two programs that start in the same data state σ and terminate normally agree on the values of the output variables. Definition 1.
Let S and S be two (sub)programs and V ⊆ V be the outputvariables. S and S are partially equivalent w.r.t. V (denoted by S ≡ V S ) if ∀ σ, σ ′ , σ ′′ ∈ Σ, v ∈ V : (( S , σ ) → ∗ ( E, σ ′ ) ∧ ( S , σ ) → ∗ ( E, σ ′′ )) ⇒ σ ′ ( v ) = σ ′′ ( v ) . Our
PEQcheck approaches translates partial equivalence into verification tasksthat encode partial equivalence of subprograms. As already seen in the illustra-tion,
PEQcheck ’s translation relies on information about how variables areused in a subprogram. Given the above semantics, we now define the requiredusage sets formally. We start with the definition of modified variables. A variableis modified by a program when its value changes.
Definition 2.
Let S be a (sub)program. The variables modified by S are: M ( S ) := { v ∈ V | ∃ σ, σ ′ ∈ Σ : ( S, σ ) → ∗ ( · , σ ′ ) ∧ σ ( v ) = σ ′ ( v ) } . Side-effect free programs modify variables only by assignments. For them, theset M ( S ) of modified variables can be overapproximated by the set of variablesthat occur on the left-hand side of an assignment in S .The set UB contains all variables v that may be used before they are defined.For programs, these are the variables used uninitialized on some program execu-tion. Formally, there exists a path such that variable v occurs in an expressionof an operation op i on the path and v does not occur on the left-hand side of anassignment on the first i-1 steps of the path. ocalized and Context-aware Checking of Functional Equivalence 7 Definition 3.
Let S be a (sub)program. Its variables used before definition inexecution p = ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) are: UB ex ( p ) := { v ∈ V | ∃ ≤ i ≤ n : ∀ ≤ j < i : op j v := aexpr ; ∧ ( op i ≡ v ′ := aexpr ; ∧ v ∈ V ( aexpr ) ∨ op i ≡ bexpr ∧ v ∈ V ( bexpr )) } The variables used before definition in S are UB ( S ) := S p ∈ ex ( S ) UB ex ( p ) . In practice, one can approximate UB using an uninitialized variable analysis onsubprogram S i or perform a reaching definition analysis [24] on the program S .Finally, we define the usage set L that contains all variables that are live aftera subprogram S of program S . Basically, a variable is live after a subprogram S if it is live at a program S ′′ that can be reached from S after the execution of S .Variables are live at a (sub)program if they may be used in the (sub)programbefore they are redefined. To properly treat output variables, we assume thatthey are used after the program terminated normally. Thus, the set L dependsnot only on the subprogram, but also on the program and the output variables.Note that the following definition of L only covers subprograms that do notoccur in parallel statements, e.g., all subprograms that we may compare in ourequivalence checks. Definition 4.
Let S be program, S a subprogram of S and V ⊆ V the outputvariables. We define the variables live at S by L ( S , V ) := { v ∈ V | ∃ S op → . . . , op n → S n ∈ syn P ( S ) : ∀ i ∈ [1 , k ] : op k v := expr ; ∧ (( k = n − ∧ ( op n ≡ v ′ := aexpr ; ∧ v ∈ V ( aexpr ) ∨ op n ≡ bexpr ∧ v ∈ V ( bexpr ))) ∨ k = n ∧ S n = E ∧ v ∈ V ) } . The variables live in S after S are: L ( S , S, V ) := { v ∈ V | ∃ σ, σ ′ ∈ Σ : ( S, σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( S ) ∧ ( S ′ = S ∧ v ∈ L ( E, V ) ∨ S ′ = S ; S ′′ ∧ v ∈ L ( S ′′ , V )) } In practice, one would use a live variable analysis [24] to compute the set L . In this section, we present how our
PEQcheck approach encodes the partialequivalence of two subprograms into a verification task and show that
PEQ-check is sound. Furthermore, we discuss limitations of
PEQcheck .To encode partial equivalence of two subprograms, we need to ensure thatboth get equal inputs. Two approaches exist in the literature: (1) store thestate before executing the first subprogram, save the results, and restore thestate [20,31] or (2) assign equal values to the inputs of the two subprograms [15,41].To store and restore the state, one can either use dedicated methods [31] to writeand read them from (persistent) memory or copy the variable values to and fromadditional variables that do not occur in the program. The first option requires
M.-C. Jakobs the verifier to understand the dedicated methods, which cannot be assumed forarbitrary verifiers, and we, therefore, exclude it. Similar to the store and restoreapproach with additional variables, also the approach (2) needs to duplicate(shared, modified) variables. While the first solution has the advantage that itdoes not need to rename variables, we think that assigning equal values beforeexecuting the subprograms allows the verifier to more easily learn about therelation of the variables in the two subprograms. Thus, our encoding, which wediscuss next, follows approach (2).Remember from Section 1.1 that the
PEQcheck encoding consists of threeparts: (1) the (equal) initialization of variables, (2) the execution of the two sub-programs, and (3) checking equivalence of output variables. We start to describethe generic construction of the individual parts, deferring the constraints on theinputs for the moment and forgoing to label program statements.The goal of the initialization part is to ensure that the common inputs areequal. While equalization of inputs is not necessary for soundness, we use it toincrease the success of equivalence checking. Without initialization, the verifi-cation of an equivalence tasks only succeeds if the two subprograms are equalindependently of the input. The initialization aims at making duplicated inputvariables equal and assumes that non-duplicated (input) variables will not bemodified by any of the two subprograms.
PEQcheck will ensure this assump-tion. There exist two alternatives to ensure equivalent inputs: (1) assign the du-plicated variable the value of the variable or (2) assign the variable the value ofthe duplicated variable. Since the
PEQcheck encoding starts with the initiali-zation, at the beginning of a program all variables are unconstrained, and bothvariables are part of V , it does not matter which alternative one chooses. Wechose alternative (2), which reflects that we initialize the variables of the paral-lelized code segment with the values of the counterparts in the sequential codesegment. Given a renaming function ρ and a sequence V of inputs that must beequal and are duplicated, we add one assignment per such variable that assignsto the variable the value of the duplicated variable. init ( ρ, V ) := E if V = hi v := ρ ( v ); if V = h v i v := ρ ( v ); init ( ρ, V ′ ) if V = h v i ◦ V ′ Next, we discuss the equalization part, which should check that output variablesare equal. As for initialization, we only check equivalence of duplicated variables.We use assert statements to check equivalence. To learn which output variablesthreaten partial equivalence, we use one assert statement per output variable thatcompares the value of the original and duplicated variable. Given a renamingfunction ρ and a sequence V of outputs that must be equal and are duplicated, In practice, variables must be declared and initialized non-deterministically due todefault initialization. This is not required for our programs. In practice, the difference between the two alternatives is whether the variable or itsduplication are initialized non-deterministically before this initialization part.ocalized and Context-aware Checking of Functional Equivalence 9 the following definition implements our idea of the equalization part. equal ( ρ, V ) := E if V = hi assert ρ ( v ) == v ; if V = h v i assert ρ ( v ) == v ; equal ( ρ, V ′ ) if V = h v i ◦ V ′ Now, we can put everything together into a task for equivalence checking. Asshown by the following definition, we need a renaming function and two setsof variables. Set I describes the variables that should be equally initialized andset C those that should be checked for equivalence. Given these information, wesequentially compose the initialization, the renamed subprogram S , the sub-program S , and the equalization. We use the function toSeq to transform a setof variables into a sequence, e.g., using their lexical ordering, and, thus, makethem available for init and equal . eq task ( S , S , ρ, I, C ) := init ( ρ, toSeq( I )); R ( S , ρ ); S ; equal ( ρ, toSeq( C ))So far, we generically described how to encode an equivalence task. To be sound,we need to carefully choose the inputs, especially the renaming function ρ andvariables I for the initialization.First, let us look at the renaming function. To guarantee that the initial-ization part equalizes v and its duplicate ρ ( v ) for all variables v in the set I ,we require that (a) renaming does not mess up the initialization, i.e., ∀ v ∈ I : ρ ( v ) = v ∨ ρ ( v ) / ∈ I . To ensure that the execution of subprograms R ( S , ρ ) and S do not interfere with each other, the renaming function must (b) prohibitinterfering, i.e., ∀ v ∈ V ( S ) ∪ M ( S ) : ρ ( v ) / ∈ M ( S ) and ∀ v ∈ M ( S ) : ρ ( v ) / ∈V ( S ) ∪ M ( S ). We call renaming functions fulfilling the latter constraints ap-propriate for renaming . The renaming function ρ sum2 introduced in the previoussection is appropriate for renaming.To ensure that both subprograms S and S get the same input, the initial-ization part needs to consider all variables that are duplicated and used beforedefinition in S or S .In practice, we consider overapproximations UB ( S ) ⊆ U ⊆ V ( S ) and UB ( S ) ⊆ U ⊆ V ( S ) of the variables used before definition and overapprox-imations M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ⊆ M ⊆ V ( S ) of the modifiedvariables. We use this information to restrict the equivalence check to a subset C ⊆ M ∪ M of the possibly modified variables. The concrete choice of C de-pends on variable liveness and, thus, the subset of output variables. Furthermore,we build a bijective renaming function ρ switch that switches all modified variables( M ∪ M ) with a non-program variable and keeps all other variables. Given aninjective function switch : M ∪ M → V \ ( V ( S ) ∪ V ( S )), which describeshow to switch, we define ρ switch as follows: for all variables v ∈ V the renamedvariable is ρ switch ( v ) = switch( v ) if v ∈ M ∪ M , ρ switch ( v ) = v m if there exists v m ∈ M ∪ M and switch( v m ) = v , and ρ switch ( v ) = v in all other cases. Note While the initialization part is not required for soundness, if we include initialization,it must work properly for
PEQcheck to be sound. We rename the variables in img (switch) to guarantee bijectivity.0 M.-C. Jakobs that ρ switch is renaming function appropriate for renaming and fulfills condition(a) for I = ( U ∩ U ) ∩ ( M ∪ M ) , which we will use during task construction.In our example, we use switch sum2 : sum sum s to generate ρ sum2 .Next, we discuss soundness of our encoding. Our encoding should ensurethat if the verification of the encoded equivalence task succeeds, i.e., none ofits executions violates an assertion, then the two subprogram S and S will bepartially equivalent with respect to the unmodified variables and the variables C ,which are checked for equivalence. The following theorem ensures this propertywhen creating the equivalence task with the inputs discussed above. Theorem 1.
Let S and S be two (sub)programs, UB ( S ) ⊆ U ⊆ V ( S ) , UB ( S ) ⊆ U ⊆ V ( S ) , M ( S ) ⊆ M ⊆ V ( S ) , M ( S ) ⊆ M ⊆ V ( S ) , ρ switch a renaming function, and C ⊆ M ∪ M . Define the equivalence task to be S = eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C ) .If all execution ( S, σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( S ) do not violate an assertion, then S ≡ V\ (( M ( S ) ∪M ( S ) \ C ) S .Proof. See appendix A.3.The theorem above tells us how to use
PEQcheck when applying it to thecomplete program. However, our goal is to split equivalence checking of twoprograms into equivalence checking of pairs of subprograms.Given two programs S and S ′ , we assume that there exists a partial, injective replacement function γ such that S ′ can be derived from S by replacing allsubprogram S of S with S ∈ dom ( γ ) by γ ( S ). We write Γ ( S, γ ) to describethe result of this replacement. Furthermore, we assume the following: Programs E, [ E k . . . k E ] / ∈ dom ( γ ). The domain dom ( γ ) only contains subprograms of S and all subprograms in the domain dom ( γ ) do not occur in a parallel statementof S . Similarly, we assume that all subprograms in the image im ( γ ) of γ do notoccur in a parallel statement of S ′ . Thus, we e.g. ensure that thread interferencecannot invalidate the result of PEQcheck ’s equivalence checking. Note thatsuch a replacement function always exists. One can always use γ = { ( S, S ′ ) } .Given a replacement function γ , PEQcheck builds one equivalence taskper pair ( S , S ) ∈ γ . For the task generation, we consider overapproximations UB ( S ) ⊆ U ⊆ V ( S ) and UB ( S ) ⊆ U ⊆ V ( S ) of the variables used beforedefinition, overapproximations M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ⊆ M ⊆V ( S ) of the modified variables, and overapproximations L ( S , S, V ) ⊆ L ⊆ V and L ( S , S ′ , V ) ⊆ L ⊆ V of the variables live after S and S , where V denotes the output variables. Given these sets, we generate the equivalence task eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , ( M ∪ M ) ∩ ( L ∪ L )). After generation of the verification tasks,
PEQcheck verifies each verifica-tion task and declares S and S ′ to be equivalent if none of the tasks violates anassertion. The following theorem shows that the PEQcheck approach is soundwhen the variables used before definition are not overapproximated. Proved by Lemma 12 in the appendix.ocalized and Context-aware Checking of Functional Equivalence 11
Theorem 2.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. If for all ( S , S ) ∈ γ thereexists M ( S ) ⊆ M ⊆ V ( S ) , M ( S ) ⊆ M ⊆ V ( S ) , L ( S , S, V ) ⊆ L ⊆ V , L ( S , S ′ , V ) ⊆ L ⊆ V , and renaming function ρ switch such that the equivalencetask eq task ( S , S , ρ switch , ( UB ( S ) ∩UB ( S )) ∩ ( M ∪ M ) , ( M ∪ M ) ∩ ( L ∪ L )) does not violate an assertion, then S ≡ V S ′ .Proof. See appendix A.4.In practice, one typically overapproximates the variables used before defi-nition. However, our proof attempts taught us that not all overapproximationsare sound. The problem is that modifications are defined semantically while livevariables are defined syntactically. If the initialization step equalizes a variablewhose value is not identical before, its not modified in S , but assigned in S ,and becomes live in S afterwards, then the comparison in the equalization taskwill use the wrong value for the variable in S . One can circumvent this problemif the overapproximation of the modified variables for S always considers allassignments in S . Theorem 3.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. If for all ( S , S ) ∈ γ there exists overapproximations UB ( S ) ⊆ U ⊆ V ( S ) , UB ( S ) ⊆ U ⊆ V ( S ) , M ( S ) ⊆ M ⊆ V ( S ) , M ( S ) ∪ { v ∈ V | ∃ S → ∗ S k v := aexpr → S r ∈ syn P ( S ) } ⊆ M ⊆ V ( S ) , L ( S , S, V ) ⊆ L ⊆ V , L ( S , S ′ , V ) ⊆ L ⊆ V , and renaming ρ switch s.t. eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , ( M ∪ M ) ∩ ( L ∪ L )) does not violate an assertion, then S ≡ V S ′ .Proof. See appendix A.5.
While we proved soundness of our
PEQcheck approach,
PEQcheck is notcomplete, which could have been expected because functional equivalence of twoprograms is undecidable [15]. For example, our encoding misses some equiva-lences. There exist equivalent code segments like in Fig. 3 for which the verifica-tion task violates an assertion. The problem in Fig. 3 is that variable y is live, isnot used before definition, but is not defined on all program paths. One could cir-cumvent this problem by adding variables that are only modified on some pathsto the set of initialized variables. A similar problem occurs when one of the twocode segments violates an assertion. To deal with assertions assert bexpr ; in theprogram, one could replace them by while bexpr do E . Another problem is thatan equivalence task considers all input values, while during program executionthe code segments are likely only executed with a subset of them. One couldtry to determine (an overapprximation of) the input ranges for code segmentsand enhance the initialization with code that restricts the inputs to these values.However, it is unlikely that one can determine the precise ranges in all cases.Another aspect is the choice of code segments. For example, code segments must Listing 1.4.
Original program int f o o o r i g ( int x , int y ) { i f (x > return y ; } Listing 1.5.
Modified program int foo mod ( int x , int y ) { i f ( ! ( x < =0))y=1; return y ; } Listing 1.6.
Verification task int main ( ) { int x , y s , y ;x = random int ( ) ; i f (x > i f ( ! ( x < =0))y=1;a s s e r t ( y s == y ) ; return } Fig. 3.
Behaviorally equivalent original and modified subprograms for which our
PEQ-check approach fails to show equivalence
Listing 1.7.
Sequential program i nt sum seq ( i nt N) { i nt i , sum = 0 , a [N ] ; for ( i = 0 ; i < N; i ++)a [ i ] = N − i ; for ( i = 0 ; i < N; i ++)sum += a [ i ] ; return sum ; } Listing 1.8.
Parallelized program i nt sum par ( i nt N) { i nt i , sum = 0 , a [N ] ; for ( i = 0 ; i < N; i ++)a [ i ] = i + 1 ; for ( i = 0 ; i < N; i ++)sum += a [ i ] ; return sum ; } Fig. 4.
Behaviorally equivalent sequential and parallelized program whose first codesegments (highlighted in orange) are not identical be subprograms and they must not occur in a parallel statement. Note that thisonly limits the granularity of code segments, but not the applicability of theapproach. More importantly, we may miss equivalent programs when using awrong choice of code segments. For example, consider the sequential and theparallelized program shown in Fig. 4 whose first for loops are not identical. Ifwe use two code segments, one per for loop, then equivalence checking fails. Incontrast, it succeeds if we choose the code segment to contain both for loops.
Our goal is to demonstrate the
PEQcheck approach and evaluate whetherlocalized equivalence checking is beneficial. To demonstrate the generality of ocalized and Context-aware Checking of Functional Equivalence 13
PEQcheck , we apply it to parallelized programs and to different versions ofsequential programs. Note that we did not compare
PEQcheck with existingapproaches that encode equivalence into program verification tasks because theyare not available [31,1] (for C programs [20,41]) or the compilation failed [15,16].
PEQcheck Implementation.
To perform equivalence checking with
PEQ-check , one must (1) determine the code segments, (2) generate the verificationtasks for the code segments, and (3) verify the tasks. So far, we have tool supportfor steps (2) and (3) and performed step (1) manually, i.e., in our examples, weinserted pragma statements and to definethe start and end of code segment i .To generate the verification tasks, we implemented a prototype tool for theapproach from Section 3. Our prototype builds on the ROSE compiler frame-work [30] (v0.9.13.0). It applies ROSE’s live analysis to detect the variableslive afterwards and runs ROSE’s reaching definition analysis to identify whichvariables are modified and which are used before definition. Since these anal-yses are intraprocedural, we overapproximate the behavior of global variablesand parameters passed. For example, we assume that global variables and non-scalar parameters are always live. Similarly, non-scalar parameters passed to andglobal variables used by another function are always modified and used beforedefinition. However, note that our prototype does not support all C features.For instance, we do not properly handle pointers and do not support all types,especially, we do not support type definitions. Furthermore, we do not supportinputs from files or standard input. Similarly, we do check outputs to files, etc.For the verification of the generated tasks, we use the two existing verifiersCIVL [36] (version 1.20 5259 with theorem prover Z3 [23] (version 4.8.8)) and CPAchecker [6] (version 1.9.1). To verify a task task.c with OpenMP con-structs, we run CIVL using the following command line. civl verify -input omp thread max=2 -checkDivisionByZero=false-checkMemoryLeak=false -timeout=300 nondet funs.c task.c Hence, we limit CIVL’s verification to 5 min and two threads. File nondet funs.c implements the random input functions, which are restricted to elements from[-5;5]. For the verification of sequential tasks task.c , we run
CPAchecker ’sdefault analysis using the following command line. scripts/cpa.sh -default -spec config/specification/Assertion.spc-timelimit 300s -preprocess task.c
We use scripts to automatically execute steps (2) and (3) on our examples.
Environmental Set Up.
We run our experiments on a machine with anIntel i7-8565U CPU (frequency of 1.8 GHz), 32 GB RAM, and an Ubuntu 18.04.To count the lines of codes, we use cloc v1.74 . Benchmark.
To check equivalence of sequential and parallelized programs,we consider four own examples and parallelized the * spec.c files from the func-tional equivalence suite (FEVS) [37]. We exclude programs diffusion1d-gd , https://cpachecker.sosy-lab.org/download.php https://github.com/AlDanial/cloc4 M.-C. Jakobs Table 1.
Results of applying
PEQcheck to a sequential program and its parallelization
LOC time enc (s) time
CIVL (s) statusBenchmark P seq P par P seg P all t Eseg t Eall t V seg t V all s seg s all tasks ments ( max )adder-s2 1 10 11 21 44 4 5 7 4 X ERRadder-s-e 1 10 11 21 44 5 5 6 4 × ERRadder-s 1 10 11 21 44 5 5 8 4 X ERRex 1 12 13 25 25 5 5 5 5
X X adder2-nd 1 15 16 30 54 5 6 82 4 X ERRadder2 2 17 20 28 28 8 5 609 304 TO TOadder-e 2 17 19 26 26 8 5 608 305 TO TOadder-nd-e 1 15 16 30 54 6 6 20 4 × ERRadder-nd 1 15 16 31 54 6 5 83 4 X ERRadder 2 17 19 26 26 8 5 608 304 TO TOdiffusion1d-nd 3 44 51 61 197 11 6 52 6 ERR/ × mem / × EXdiffusion1d 2 43 45 42 153 8 6 13 48 × mem × diffusion2d-nd 2 50 59 91 237 9 6 13 7 ERR ERRdiffusion2d 2 63 67 106 242 9 6 19 306 × mem TOfactorial2 1 11 15 28 26 6 6 8 5
X X factorial-e 1 11 14 27 25 6 5 6 5 × × factorial 1 11 12 25 23 6 6 8 5
X X gausselim-e 2 98 108 64 228 9 6 23 5 × mem ERRgausselim 3 100 111 64 229 11 6 28 5 × mem ERRintegrate 1 59 60 150 163 7 8 1 1 EX EXlaplace 3 48 55 71 148 11 6 11 3 EX/ × mem EXmatmat 1 33 37 78 133 6 6 304 5 TO ERRmean-e 1 17 18 31 54 6 5 7 6 × ERRmean 1 17 18 31 54 6 6 81 7 X ERRwave1d-nd 2 99 101 61 315 9 7 13 12 × mem ERRwave1d 2 87 89 136 295 9 7 17 309 × mem TO diffusion2d-gd , and nbody due to missing header files. We also exclude fib ,which we failed to parallelize, and use the iterative instead of the recursive fac-torial implementation. To deal with I/O inputs, we replaced them by calls torandom functions. We also replaced the assert statements. As local code seg-ments, we use the parallel code units.To check equivalence of two sequential program versions, we consider thenon-recursive programs used in Rˆeve [12] (except for loop4 and loop5 , whichwere not available). As local code segments, we selected the smallest subprograminfluenced by a change.To evaluate whether localized equivalence checking is beneficial, we considera second set of code segments, named all,. This set contains one code segmentper program that covers the complete program. Table 1 shows the results of applying
PEQcheck to the benchmark tasks withthe parallelized programs. The first section of the table shows our own examples( ex is the example from Fig. 1) and the second shows the FEVS examples.Benchmark tasks ending on -e are incorrect parallelizations. ocalized and Context-aware Checking of Functional Equivalence 15 For each benchmark task, we report the number of local code segments ,the lines of code of the sequential and parallelized program as well as the lines ofcode of the verification tasks for both configurations of code segments. If morethan one verification task exists in the local configuration seg, we report thelargest number of lines of code among all tasks. For both configurations of codesegments, we also provide the total time spent on generating the verificationtasks plus the total time spent on verification and the verification results.First, let us look at the results using PEQcheck with local code segments(configuration seg). Studying the lines of code (LOC), we observe that an en-coded verification task is often larger than the sequential and parallelized pro-gram. One reason for the larger size is that the programs are often rather small,i.e., the code segments dominate the program code and the tasks contain the codeof the sequential and the parallelized code segment. Additionally, the verificationtask requires statements for initialization and for inspection of the equivalence ofoutput variables. Inspecting column t Eseg , which reports the time for generatingall verification tasks of a benchmark task, we notice that task generation is ratherfast. This may change if the input programs get significantly larger. Finally, letus consider the verification of the generated equivalence tasks (columns t V seg and s seg ). We observe that CIVL fails to verify some equivalence tasks due to anerror (ERR), an exception (EX), or a time out (TO). In case of status × mem ,CIVL detects an out of bounds access or an invalid dereference. These viola-tions exist because in the generated tasks the size of pointer-based arrays andtheir size assumed by the program mismatch. Note that this is not a problemof the PEQcheck approach in general. On the one hand, it is C specific issuewith our
PEQcheck implementation, which we plan to fix in future. On theother hand, executions causing an out of bounds access or an invalid dereferencedo not terminate normally and, thus, do not need to be considered for partialequivalence. Considering status X and × , we notice that equivalence ( X ) is onlyreported for equivalent tasks and that the inequivalence ( × ) of some tasks isdetected. Thus, localized equivalence checking with PEQcheck can correctlydetect (in)equivalence.Next, let us compare
PEQcheck with localized equivalence checking (con-figuration seg) against all at once checking (configuration all). Although theencoding times are similar in both configurations, we observe that the tasks forconfiguration all are rarely smaller and often large than the local tasks. This canbe an indication that localized checking reduces complexity. Moreover, the veri-fication in configuration all fails more often. One reason for more errors are thehandling of (random) input functions. The encoding uses static local variablesto ensure that the sequential and parallelized code get the same identical valuefor their ith call to a random function. CIVL seems to have problems with suchvariables. Comparing the tasks for which both configurations reported either X or × , we observe little difference between the two configurations. Summingup, localized equivalence checking is beneficial for our examples. By construction, there exists one code segment per task in the set all.6 M.-C. Jakobs
Table 2.
Results of applying
PEQcheck to pairs of sequential programs
LOC time enc (s) time
CPA X (s) statusBenchmark P orig P mod P seg P all t Eseg t Eall t V seg t V all s seg s all tasks ments ( max )barthe 1 16 16 39 35 6 5 6 304 × TObarthe-e 1 19 22 44 44 6 6 7 326 × TObarthe2 1 14 14 31 29 5 5 379 327 TO TObarthe2-big 1 19 19 33 39 5 5 349 346 TO TObarthe2-big2 1 24 24 33 49 6 5 351 340 TO TObug15 2 13 13 24 25 6 5 62 6
X X digits10 1 29 32 75 75 5 5 23 27
X X digits10-e 1 26 29 62 62 5 5 4 5 × × loop 1 11 11 24 24 6 5 343 368 TO TOloop2 1 11 11 26 24 5 5 348 368 TO TOloop3 1 14 14 26 32 5 6 5 420 × TOloop5-e 1 14 14 29 29 6 6 6 7 × × nested-while 2 21 19 26 43 7 5 9 377 X TOnested-while-e 2 20 18 26 41 7 5 10 8 × × simple-loop 1 9 9 17 17 6 6 6 5
X X simple-loop-e 1 10 10 18 18 5 5 5 5 × × while-if 1 20 20 55 53 5 5 8 5
X X while-if-e 1 17 17 42 40 5 6 9 6 × ×
Our second experiment illustrates that the
PEQcheck approach is not limitedto parallelization. Table 2 shows our evaluation results for the pairs of sequentialprograms from our benchmark. The structure of Tab. 2 is similar to Tab. 1.Again, let us look at the results using
PEQcheck with local code segments(configuration seg). Looking at Tab. 2, we observe that also the sequential ver-ification tasks are typically larger than the two input programs. Additionally,task generation is fast. Considering the verification, we observe that the veri-fier
CPAchecker times out (status TO) for some tasks. Additionally,
CPA-checker reports an inequivlaence for barthe and loop3 , although these twobenchmark tasks represent behaviorally equivalent modifications. Our inspectionreveals that the equivalence tasks are indeed inequivalent, but the two programsexecute the two segments with a restricted set of inputs and are therefore equiv-alent. Nevertheless, equivalence (status X ) is reported for some of the equivalenttasks. Moreover, for all pairs of programs that are inequivalent (i.e., bench-mark task with suffix -e ), inequivalence is detected (i.e., status × is reported).Thus, localized equivalence checking with PEQcheck can also correctly detect(in)equivalence for pairs of sequential programs.Next, let us compare
PEQcheck with localized equivalence checking (con-figuration seg) against all at once checking (configuration all). In this set ofbenchmarks, configuration all is identical to checking equivalence of functions,the approach typically taken in the related work. Again, the times for the en-coding are similar. Additionally, the sizes of the verification tasks do not differsignificantly. The reasons are that even the localized segments enclose most ofthe functions’ code, often only excluding variable declaration and initialization.Nevertheless, the verification in configuration all times out more often and ex- ocalized and Context-aware Checking of Functional Equivalence 17 cept for bug15 is not significantly faster. Only in case of bug15 , the verificationin configuration all profits from restricted input values. Hence, also for the se-quential examples localized equivalence checking can be beneficial.
Checking functional equivalence is a special case of relational program verifica-tion [5,43]. To verify relational properties between two programs, Barthe et al.suggest to merge them into a product program [4] and verify the product pro-gram. A product program integrates the two programs tighter than a sequentialcomposition because it executes synchronous steps in lockstep.Still, lots of approaches directly focus on function equivalence. Some ap-proaches [35,38,3,40,34] transform the two programs, which should be provenequivalent, into models and check model equivalence. Other approaches, e.g.,[46,33,10,9], aim at finding a (bi)simulation relation between the two programs.Pathg [45] checks equivalence of an OpenMP program and its sequential ver-sion (the program without the OpenMP directives). It assumes that only raceconditions can cause inequivalence and, therefore, apply symbolic simulationon segments with race conditions to check whether the races affect the out-put. Fractal symbolic analysis [21] transforms the two programs, which shouldbe proven equivalent, into two simpler programs whose equivalence implies theequivalence of the original programs. Then, it compares the guarded symbolicexpressions (descriptions of the effect of a program on a variable) of all variablesthat are modified and live. Rˆeve [12] translates the equivalence of two deter-ministic functions into verification conditions, more concretely, Horn constraintswith uninterpreted symbols. DSE [28] and ARDiff [2] use symbolic execution tocompute the summaries of two functions and check the logical equivalence ofthe summaries to decide the functional equivalence of the two functions. DSEand ARDiff abstract certain common code regions by uninterpreted functions.In contrast, we analyze the equivalence of code regions that differ.A common approach, which we also follow, is to encode the equivalence checkas a program [15,16,31,20,41,8,36,1]. Often, the encoded program equally, butnon-deterministically initializes the inputs (e.g., global variables, parameters),sequentially executes the two functions, and finally checks the equivalence of theoutputs (e.g., global variables, return values). Regression verification [15,16], asimplemented in RVT, SymDiff [20], and RIE [41] apply this idea for each matchedpair of sequential functions. RVT and SymDiff use uninterpreted functions forfunction calls and RIE uses summaries. While RVT [15,16] and RIE [41] renamevariables and ensure that matching variables get the same input values, Sym-Diff [20] and UC-Klee [31] store and restore the initial state and save the stateafter each function execution. Moreover, RIE [41] considers heap equivalenceinstead of equivalence of output variables. Also, approaches for parallel programsexist. Chaki et al. [8] show how to encode equivalence of multi-threaded programs RVT only replaces calls that are recursive or already proven equivalent.8 M.-C. Jakobs into one sequential verification task per function pair. CIVL [36] can encode andcheck functional equivalence for concurrent programs using pthreads, OpenMP,MPI, etc. It builds a single composite program and equalizes the inputs. However,CIVL requires that input and output variables are manually specified. Abadi etal. [1] describe a method to encode functional equivalence of a sequential anda parallelized code segment. Their method wraps the two code segments intotwo separate functions, which get the same input variables, but different outputvariables. Input and output variable detection uses dataflow analyses, but thedetection is not further specified. To be functionally equivalent, the input andoutput variables of the two segments must be identical.Some approaches [26,27,28,18] go beyond the detection of equivalence andoutput under which conditions the two programs are equivalent.
Program refactoring is a common task in software development and ensuringthe correctness of a refactoring, i.e., ensuring that the refactoring is behaviorpreserving, has obtained lots of attention. Since programs are rarely formallyspecified, one typically uses the original program as behavior specification andshows that original and refactored program are functionally equivalent.We propose
PEQcheck to check functional equivalence of original and refac-tored program and proved its soundness.
PEQcheck reduces equivalence check-ing to program verification. Motivated by rather local OpenMP parallelizations,
PEQcheck generates one verification task per modified code segment, e.g., aparallelized code segment.
PEQcheck ’s other novelty is that it takes the contextof the code segments, i.e., how variables are used in and after the code segments,into account when creating the verification tasks. Together, context-awarenessand localized checking aim at reducing the complexity of the verification task.Our experiments show that such a reduction is indeed achieved for some ex-amples. Furthermore, we demonstrate that
PEQcheck is not limited to equiv-alence checking of sequential programs and their parallelization, but that it canbe used with pairs of sequential programs, too. While our experiments also tes-tify one of
PEQcheck ’s incompleteness issues (overapproximation of the inputspace may lead to a missed equivalence), this problem is common in many modu-lar verification approaches. All in all, our evaluation shows that the
PEQcheck approach is feasible and can be beneficial.
Acknowledgements
This work was funded by the Hessian LOEWE initiativewithin the Software-Factory 4.0 project.
References
1. Abadi, M., Keidar-Barner, S., Pidan, D., Veksler, T.: Verifying parallel code af-ter refactoring using equivalence checking. Int. J. Parallel Program. (1), 59–73(2019), https://doi.org/10.1007/s10766-017-0548-4ocalized and Context-aware Checking of Functional Equivalence 192. Badihi, S., Akinotcho, F., Li, Y., Rubin, J.: Ardiff: scaling program equivalencechecking via iterative abstraction and refinement of common code. In: Proc. FSE.pp. 13–24. ACM (2020), https://doi.org/10.1145/3368089.34097573. Bandyopadhyay, S., Banerjee, K.: PRESGen: A fully automatic equiv-alence checker for validating optimizing and parallelizing transfor-mations. In: Proc. SEM4HPC@HPDC. pp. 13–20. ACM (2017),https://doi.org/10.1145/3085158.30861584. Barthe, G., Crespo, J.M., Kunz, C.: Relational verification using prod-uct programs. In: Proc. FM. pp. 200–214. LNCS 6664, Springer (2011),https://doi.org/10.1007/978-3-642-21437-0 175. Benton, N.: Simple relational correctness proofs for static analyses andprogram transformations. In: Proc. POPL. pp. 14–25. ACM (2004),https://doi.org/10.1145/964001.9640036. Beyer, D., Keremoglu, M.E.: CPAchecker : A tool for configurable soft-ware verification. In: Proc. CAV. pp. 184–190. LNCS 6806, Springer (2011),https://doi.org/10.1007/978-3-642-22110-1 167. Beyer, D., L¨owe, S., Novikov, E., Stahlbauer, A., Wendler, P.: Precision reusefor efficient regression verification. In: Proc. FSE. pp. 389–399. ACM (2013),https://doi.org/10.1145/2491411.24914298. Chaki, S., Gurfinkel, A., Strichman, O.: Regression verification for multi-threaded programs. In: Proc. VMCAI. pp. 119–135. LNCS 7148, Springer (2012),https://doi.org/10.1007/978-3-642-27940-9 99. Churchill, B.R., Padon, O., Sharma, R., Aiken, A.: Semantic program align-ment for equivalence checking. In: Proc. PLDI. pp. 1027–1040. ACM (2019),https://doi.org/10.1145/3314221.331459610. Dahiya, M., Bansal, S.: Black-box equivalence checking across compiler op-timizations. In: Proc. APLAS. pp. 127–147. LNCS 10695, Springer (2017),https://doi.org/10.1007/978-3-319-71237-6 711. D’Silva, V., Kroening, D., Weissenbacher, G.: A survey of automated tech-niques for formal software verification. TCAD (7), 1165–1178 (2008),https://doi.org/10.1109/TCAD.2008.92341012. Felsing, D., Grebing, S., Klebanov, V., R¨ummer, P., Ulbrich, M.: Au-tomating regression verification. In: Proc. ASE. pp. 349–360. ACM (2014),https://doi.org/10.1145/2642937.264298713. Fowler, M.: Refactoring - Improving the Design of Existing Code. Addison-Wesley(1999), http://martinfowler.com/books/refactoring.html14. Garrido, A., Meseguer, J.: Formal specification and verification ofJava refactorings. In: Proc. SCAM. pp. 165–174. IEEE (2006),https://doi.ieeecomputersociety.org/10.1109/SCAM.2006.1615. Godlin, B., Strichman, O.: Regression verification. In: Proc. DAC. pp. 466–471.ACM (2009), https://doi.org/10.1145/1629911.163003416. Godlin, B., Strichman, O.: Regression verification: proving the equivalence of sim-ilar programs. STVR (4),427–435 (2011), https://doi.org/10.1007/s11786-011-0101-638. Siegel, S.F., Zirkel, T.K.: TASS: the toolkit for accurate scientificsoftware. Mathematics in Computer Science (4), 395–426 (2011),https://doi.org/10.1007/s11786-011-0100-739. Sultana, N., Thompson, S.J.: Mechanical verification of refactorings. In: Proc.PEPM. pp. 51–60. ACM (2008), https://doi.org/10.1145/1328408.132841740. Verdoolaege, S., Janssens, G., Bruynooghe, M.: Equivalence checking of staticaffine programs using widening to handle recurrences. In: Proc. CAV. pp. 599–613. LNCS 5643, Springer (2009), https://doi.org/10.1007/978-3-642-02658-4 4441. Wood, T., Drossopoulou, S., Lahiri, S.K., Eisenbach, S.: Modular ver-ification of procedure equivalence in the presence of memory alloca-tion. In: Proc. ESOP. pp. 937–963. LNCS 10201, Springer (2017),https://doi.org/10.1007/978-3-662-54434-1 3542. Yang, G., Dwyer, M.B., Rothermel, G.: Regression model checking. In: Proc. ICSM.pp. 115–124. IEEE (2009), https://doi.org/10.1109/ICSM.2009.530633443. Yang, H.: Relational separation logic. TCS (1-3), 308–334 (2007),https://doi.org/10.1016/j.tcs.2006.12.03644. Yoo, S., Harman, M.: Regression testing minimization, selection and prior-itization: a survey. Softw. Test. Verification Reliab. (2), 67–120 (2012),https://doi.org/10.1002/stv.43045. Yu, F., Yang, S., Wang, F., Chen, G., Chan, C.: Symbolic consistency check-ing of OpenMP parallel programs. In: Proc. LCTES. pp. 139–148. ACM (2012),https://doi.org/10.1145/2248418.224843846. Zaks, A., Pnueli, A.: CoVaC: Compiler validation by program analysis ofthe cross-product. In: Proc. FM. pp. 35–51. LNCS 5014, Springer (2008),https://doi.org/10.1007/978-3-540-68237-0 52 M.-C. Jakobs A Proofs
This appendix contains the proofs of our theorems.
A.1 Auxiliary Lemmas on Program ExecutionsLemma 1.
Let S be a program. ∀ p = ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) : ∀ σ ′ ∈ Σ : σ = | UB ex ( p ) σ ′ : ∃ ( S , σ ′ ) op → . . . op n → ( S n , σ ′ n ) ∈ ex ( S ) : σ n = | { v ∈V| σ v )= σ ′ v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ n Proof.
Prove by induction on the length of the executions. Show for all pro-grams S that for all executions of length n the following holds: ∀ p = ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) : ∀ σ ′ ∈ Σ : σ = | UB ex ( p ) σ ′ : ∃ ( S , σ ′ ) op → . . . op n → ( S n , σ ′ n ) ∈ ex ( S ) : σ n = | { v ∈V| σ v )= σ ′ v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ n Base case (n=0):
Let S and σ ′ be arbitrary. By definition, ( S , σ ′ ) ∈ ex ( S ).Since n = 0, we have { v ∈ V | σ ( v ) = σ ′ ( v ) ∨ ∃ ≤ i ≤ n : op i ≡ v := expr ; } = { v ∈ V | σ ( v ) = σ ′ ( v ) } and σ = σ n and σ ′ = σ ′ n . The hypothesis follows. Step case (n-1 → n): Let S , p = ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) and σ ′ ∈ Σ with σ = | UB ex ( p ) σ ′ be arbitrary. By definition, p ′ = ( S , σ ) . . . op n → ( S n , σ n ) ∈ ex ( S ). Consider three cases: Case op ≡ nop Due to semantics, S starts with E or [ E k . . . k E ], σ = σ ,and ( S , σ ′ ) nop → ( S , σ ′ ). Furthermore, { v ∈ V | σ ( v ) = σ ′ ( v ) ∨ ∃ ≤ i ≤ n : op i ≡ v := expr ; } = { v ∈ V | σ ( v ) = σ ′ ( v ) ∨ ∃ ≤ i ≤ n : op i ≡ v := expr ; } and by definition UB ex ( p ′ ) ⊆ UB ex ( p ). By induction hypothesis, ∃ ( S , σ ′ ) op → . . . op n → ( S n , σ ′ n ) ∈ ex ( S ) : σ ′ = σ ′ ∧ σ n = | { v ∈V| σ v )= σ ′ v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ n .The induction hypothesis follows. Case op ≡ bexpr By definition, V ( bexpr ) ⊆ UB ex ( p ). Thus, σ ( bexpr ) = σ ′ ( bexpr ). Due to semantics, ( S , σ ′ ) bexpr → ( S , σ ′ ) and ( S , σ ) bexpr → ( S , σ )implies σ = σ . Furthermore, { v ∈ V | σ ( v ) = σ ′ ( v ) ∨ ∃ ≤ i ≤ n : op i ≡ v := expr ; } = { v ∈ V | σ ( v ) = σ ′ ( v ) ∨ ∃ ≤ i ≤ n : op i ≡ v := expr ; } andby definition UB ex ( p ′ ) ⊆ UB ex ( p ). By induction hypothesis, ∃ ( S , σ ′ ) op → . . . op n → ( S n , σ ′ n ) ∈ ex ( S ) : σ ′ = σ ′ ∧ σ n = | { v ∈V| σ v )= σ ′ v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ n . Theinduction hypothesis follows. Case op ≡ v := aexpr ; By definition, we get V ( aexpr ) ⊆ UB ex ( p ). Thus, σ ( aexpr ) = σ ′ ( aexpr ). Due to semantics, ( S , σ ) v := aexpr → ( S , σ ) impliesthat σ = σ [ v := σ ( aexpr )] and furthermore, ( S , σ ′ ) v := aexpr → ( S , σ ′ ) with σ ′ = σ ′ [ v := σ ′ ( aexpr )] = σ ′ [ v := σ ( aexpr )]. Thus, we infer the following: σ = | { v ∈V| σ v )= σ ′ v ) ∨∃ ≤ i ≤ opi ≡ v := expr ; } σ ′ . Moreover, { v ∈ V | σ ( v ) = σ ′ ( v ) ∨∃ ≤ i ≤ n : op i ≡ v := expr ; } = { v ∈ V | σ ( v ) = σ ′ ( v ) ∨ ∃ ≤ i ≤ n : op i ≡ Since ¬ bexpr is boolean expression, too, it is covered by this case.ocalized and Context-aware Checking of Functional Equivalence 23 v := expr ; } and by definition UB ex ( p ′ ) ⊆ ( UB ex ( p ) ∪{ v } ). By induction hypothe-sis, ∃ ( S , σ ′ ) op → . . . op n → ( S n , σ ′ n ) ∈ ex ( S ) : σ n = | { v ∈V| σ v )= σ ′ v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ n . The hypothesis follows. Lemma 2.
Let S be a program. ∀ σ ∈ Σ : ( S, σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ) = ⇒ σ = | V \M ( S ) σ ′ Proof.
Prove by induction on the length of the executions. Show for all pro-grams S that ∀ σ ∈ Σ : ( S, σ ) → n ( E, σ ′ ) ∈ ex ( S ) = ⇒ σ = | V \M ( S ) σ ′ . Base case (n=0)
Then, S = E and σ = σ . The hypothesis follows. Step case (n-1 → n): Let S be arbitrary and p = ( S , σ ) op → . . . op n → ( E, σ n ) ∈ ex ( S ). By definition p ′ = ( S , σ ) op → . . . op n → ( E, σ n ) ∈ ex ( S ) and M ( S ) ⊆ M ( S ). Consider two cases: Case op ≡ bexpr or op = nop Due to semantics, σ = σ . By induction, σ = | V \M ( S σ n . Hence, σ = | V \M ( S ) σ n . Case op ≡ v := aexpr ; Due to semantics, σ = σ [ v := σ ( aexpr )] and,hence, σ = | V\{ v } σ . By induction, σ = | V \M ( S σ n . Since M ( S ) ∪{ v } ⊆ M ( S ),we conclude σ = | V \M ( S ) σ n . Lemma 3.
Let S be a program and ρ be a renaming function. ∀ ( S , σ ) op → ( S , σ ) ∈ ex ( S ) : ∃ ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → ( S , ρ ) , ρ ( σ )) ∈ ex ( R ( S, ρ )) Proof.
Prove by induction over the length n of the derivation of ( S , σ ) op → ( S , σ ) that there exists ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → ( S , ρ ) , ρ ( σ )). Base case (n=1)
Due to semantics, S is an assignment, assert statement,if- or while-statement, empty parallel statement, or a sequence starting with anempty program. Consider eight cases. Case 1 ( S ≡ v := ℓ aexpr ; ) Then, R ( S , ρ ) = ρ ( v ) := ℓ R ( aexpr, ρ );. Dueto the semantics, we conclude that ( S , σ ) v := aexpr ; → ( E, σ [ v := σ ( expr )])and ( R ( S, ρ ) , ρ ( σ )) ρ ( v ):= R ( aexpr,ρ ); → ( E, ρ ( σ )[ ρ ( v ) := ρ ( σ )( R ( aexpr, ρ ))]) ∈ ex ( R ( S , ρ )) By definition of ρ ( σ ), ρ ( σ )( R ( aexpr, ρ )) = σ ( aexpr ). We con-clude that ρ ( σ )[ ρ ( v ) := ρ ( σ )( R ( aexpr, ρ ))] = ρ ( σ )[ ρ ( v ) := σ ( aexpr )] = ρ ( σ [ v := σ ( aexpr )]). Since R ( E, ρ ) = E and R ( S , ρ ) = ρ ( v ) := ℓ R ( aexpr, ρ );,the hypothesis follows. Case 2 ( S ≡ assert ℓ bexpr ; ) Then, R ( S , ρ ) = assert ℓ R ( bexpr, ρ );. Dueto the semantics, ( S , σ ) bexpr → ( S , σ ) implies σ = σ , σ ( bexpr ) = true , and S = E . Since true = σ ( bexpr ) = ρ ( σ )( R ( bexpr, ρ )), we conclude from thesemantics that ( R ( S, ρ ) , ρ ( σ )) R ( bexpr,ρ ) → ( E, σ ′ ) ∈ ex ( R ( S , ρ )) and σ ′ = ρ ( σ ).Since R ( E, ρ ) = E , the hypothesis follows. Case 3 ( S ≡ if ℓ bexpr then S ′ else S ′′ ∧ σ ( bexpr ) ) Then, R ( S, ρ ) = if ℓ R ( bexpr, ρ ) then R ( S ′ , ρ ) else R ( S ′′ , ρ ). Due to the semantics, ( S , σ ) bexpr → ( S , σ ) with σ = σ , and S = S ′ . Since true = σ ( bexpr ) = ρ ( σ )( R ( bexpr, ρ )),we conclude from the semantics that ( R ( S , ρ ) , ρ ( σ )) R ( bexpr,ρ ) → ( R ( S ′ , ρ ) , ρ ( σ )).Since σ = σ , the induction hypothesis follows. Case 4 ( S ≡ if ℓ bexpr then S ′ else S ′′ ∧¬ σ ( bexpr ) ) Analogously to case 3.
Case 5 ( S ≡ while ℓ bexpr do S ′ ∧ σ ( bexpr ) ) We infer that R ( S, ρ ) = while ℓ ρ ( bexpr ) do R ( S ′ , ρ ). Due to the semantics, ( S , σ ) bexpr → ( S , σ ) with σ = σ , and S = S ′ ; S . By definition of ρ ( σ ), ρ ( σ )( R ( bexpr, ρ )) = σ ( bexpr ) = true . Thus, ( R ( S , ρ ) , ρ ( σ )) R ( bexpr,ρ ) → ( R ( S ′ , ρ ); R ( S , ρ ) , ρ ( σ )). Since R ( S , ρ ) = R ( S ′ ; S , ρ ) = R ( S ′ , ρ ); R ( S , ρ ), the induction hypothesis follows. Case 6 ( S ≡ while ℓ bexpr do S ′ ∧ ¬ σ ( bexpr ) ) We infer that R ( S, ρ ) = while ℓ R ( bexpr, ρ ) do R ( S ′ , ρ ). Due to the semantics, ( S , σ ) ¬ bexpr → ( E, σ ). Bydefinition of ρ ( σ ), ρ ( σ )( R ( bexpr, ρ )) = σ ( bexpr ) = f alse . Due to the seman-tics, ( R ( S, ρ ) , ρ ( σ )) ¬R ( bexpr,ρ ) → ( E, ρ ( σ )). Since R ( E, ρ ) = E and ¬R ( bexpr, ρ ) = R ( ¬ bexpr, ρ ), the hypothesis follows. Case 7 ( S ≡ [ E k . . . k E ] ) Then, R ( S , ρ ) = [ E k . . . k E ]. Due to the seman-tics, ( S , σ ) nop → ( S , σ ) implies σ = σ and S = E . Due to R ( nop , ρ ) = nop ,also ( R ( S , ρ ) , ρ ( σ )) R ( nop ,ρ ) → ( E, ρ ( σ )) ∈ ex ( R ( S , ρ )). Since R ( E, ρ ) = E , thehypothesis follows. Case 8 ( S ≡ E ; S ) Then, R ( S , ρ ) = E ; R ( S, ρ ). Due to the semantics,( S , σ ) nop → ( S , σ ) implies σ = σ and S = S . Due to R ( nop , ρ ) = nop ,also ( R ( S , ρ ) , ρ ( σ )) R ( nop ,ρ ) → ( R ( S, ρ ) , ρ ( σ )) ∈ ex ( R ( S , ρ )). The hypothesisfollows. Step case (n → n+1): Consider a ordered sequence of the derivation steps,which are derived from a derivation tree for ( S , σ ) op → ( S , σ ) such that astep required by another step in the tree occurs earlier in the sequence. Since n +1 >
1, the last step in the sequence is a computational sequential compositionsteps or a parallel composition step. Consider two cases.
Case 1 ( S ≡ S ; S ′ ∧ S = E ) Then, R ( S , ρ ) = R ( S, ρ ); R ( S ′ , ρ ). Due tosemantics, there exists S, σ op ( S ′′ , σ ) that can be derived in less than n +1 steps and S = S ′′ ; S ′ . By induction, there exists ( R ( S, ρ ) , ρ ( σ )) R ( op ,ρ ) → ( S ′′ , ρ ) , ρ ( σ )). We conclude ( R ( S ; S ′ , ρ ) , ρ ( σ )) R ( op ,ρ ) → ( S ′′ , ρ ); R ( S ′ , ρ ) , ρ ( σ )).Since R ( S ′ , ρ ); R ( S ′′ , ρ ) = R ( S ′ ; S ′′ , ρ ), the induction hypothesis follows. Case 2 ( S ≡ [ S ′ k . . . k S ′ i k . . . k S ′ n ] ∧ ∃ j ∈ [1 , n ] : S ′ i = E ) Then, R ( S ′ , ρ ) =[ R ( S ′ , ρ ) k . . . kR ( S ′ i , ρ ) k . . . kR ( S n , ρ )]. Due to semantics, there exists j ∈ [1 , n ]such that S ′ j , σ op ( S ′′ j , σ ), which can be derived in less than n + 1 steps, and S = [ S ′ k . . . k S ′′ j k . . . k S ′ n ] ′ . By induction, there exists ( R ( S ′ j , ρ ) , ρ ( σ )) R ( op ,ρ ) → ( S ′′ j , ρ ) , ρ ( σ )). Hence, ( R ([ R ( S ′ , ρ ) k . . . kR ( S ′ j , ρ ) k . . . kR ( S n , ρ )] , ρ ) , ρ ( σ )) R ( op ,ρ ) → ([ R ( S ′ , ρ ) k . . . kR ( S ′′ j , ρ ) k . . . kR ( S n , ρ )] , ρ ( σ )). Finally, taking into account that[ R ( S ′ , ρ ) k . . . kR ( S ′′ j , ρ ) k . . . kR ( S n , ρ )] = R ([ S ′ k . . . k S ′′ j k . . . k S ′ n ] , ρ ), the induc-tion hypothesis follows. ocalized and Context-aware Checking of Functional Equivalence 25 Lemma 4.
Let S be a program and ρ be a renaming function. ∀ ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) : ∃ ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → . . . R ( op n ,ρ ) → ( R ( S n , ρ ) , ρ ( σ n )) ∈ ex ( R ( S, ρ )) Proof.
Prove by induction on the length of the executions. Show for all pro-grams S that ∀ ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) : ∃ ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → . . . R ( op n ,ρ ) → ( R ( S n , ρ ) , ρ ( σ n )) ∈ ex ( R ( S, ρ )).
Base case (n=0)
Let S and σ ∈ Σ be arbitrary. By definition, there exists( R ( S, ρ ) , ρ ( σ )) ∈ ex ( R ( S, ρ )). The induction hypothesis follows.
Step case (n-1 → n): By definition of executions, ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) implies ( S , σ ) op → . . . op n − → ( S n − , σ n − ) ∈ ex ( S ) and ( S n − , σ n − ) op n → ( S n , σ n ). Furthermore, ( S n − , σ n − ) op n → ( S n , σ n ) ∈ ex ( S n − ). By induction, ex-ists ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → . . . R ( op n − ,ρ ) → ( R ( S n − , ρ ) , ρ ( σ n − )) ∈ ex ( R ( S , ρ )).Due to Lemma 3, there exists ( R ( S n − , ρ ) , ρ ( σ n − )) R ( op n ,ρ ) → ( R ( S n , ρ ) , ρ ( σ n )) ∈ ex ( R ( S n − , ρ )). Hence, ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → ( S , ρ ) , ρ ( σ )) ∈ ex ( R ( S , ρ )). Corollary 1.
Let S be a program and ρ be a renaming function. ∀ ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → . . . R ( op n ,ρ ) → ( R ( S n , ρ ) , ρ ( σ n )) ∈ ex ( R ( S, ρ )) : ∃ ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) : Proof.
By construction, R ( S, ρ )) is a program and ρ − is a bijective function.Due to Lemma 4, ∀ ( R ( S , ρ ) , ρ ( σ )) R ( op ,ρ ) → . . . R ( op n ,ρ ) → ( R ( S n , ρ ) , ρ ( σ n )) ∈ ex ( R ( S, ρ )) ∃ ( R ( R ( S , ρ ) , ρ − ) , ρ − ( ρ ( σ ))) R ( R ( op n ,ρ ) ,ρ − ) → . . . R (( R ( op n ,ρ ) ,ρ − ) → ( R (( R ( S n , ρ ) , ρ − ) , ρ − ( ρ ( σ n ))) ∈ ex ( R ( S, ρ )). Since ρ − ◦ ρ = id , there exists( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ). Lemma 5.
Let S and S be two programs and ρ a renaming function that isappropriate for renaming. ∀ σ ∈ Σ : ( R ( S , ρ ) , σ ) → ∗ ( E, σ ) ∈ ex ( R ( S , ρ )) ∧ ( S , σ ) → ∗ ( E, σ ) ∈ ex ( S ) ⇒ ∃ ( R ( S , ρ ); S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( R ( S , ρ ); S ) : σ ′ = | V ( R ( S ,ρ )) ∪ S v ∈M ( S ρ ( v ) σ ∧ σ ′ = | V ( S ∪M ( S σ Proof.
First, show σ = | V ( S ∪M ( S σ . Due to Lemma 2, σ = | V\M ( R ( S ,ρ )) σ . Dueto Lemma 4, Corollary 1, and the definition of modified variables, M ( R ( S , ρ )) = S v ∈M ( S ) ρ ( v ). Since ρ is appropriate for renaming, we conclude ( V ( S ) ∪M ( S )) ∩M ( R ( S , ρ )) = ∅ . Hence, σ = | V ( S ∪M ( S σ .Due to Lemma 1, ∃ ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ) with σ ′ = | V ( S ∪M ( S σ . Dueto semantics, ( R ( S , ρ ); S , σ ) → ∗ ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( R ( S , ρ ); S ). FromLemma 2, we conclude σ = | V\M ( S σ ′ . Since ρ is appropriate for renaming, weconclude ( V ( R ( S , ρ )) ∪ S v ∈M ( S ) ρ ( v )) ∩ M ( S ) = ∅ . The claim follows. Lemma 6.
Let S and S ′ be two programs, γ be a replacement function such that S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. If ¬∃ S s , S s : S s ∈ dom ( γ ) ∧ ( S = S s ; S s ∨ S = S s ) , then ∀ σ, σ ′ ∈ Σ : ( S, σ ) op → ( S , σ ) ∈ ex ( S ) ∧ σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ = ⇒ ∃ ( S ′ , σ ′ ) op → ( S ′ , σ ′ ) : S ′ = Γ ( S , γ ) ∧ σ = | L ( S ,V ) ∪L ( S ′ ,V ) σ ′ .Proof. Let S and S ′ be two programs, γ be a replacement function such that S ′ = Γ ( S, γ ) and ¬∃ S s , S s : S s ∈ dom ( γ ) ∧ ( S = S s ; S s ∨ S = S s ), V ⊆ V be aset of outputs and σ, σ ′ ∈ Σ with σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ .Assume p = ( S, σ ) op → ( S , σ ) ∈ ex ( S ). By definition, UB ( S ) ∪ UB ( S ′ ) ⊆L ( S, V ) ∪ L ( S ′ , V ). Consider two cases.Case 1 ( S = E ): Due to the semantics, we conclude that either S = E ; E ,or S is not a sequential composition, but a statement. If S is an assignment, anassertion or a parallel statement, we conclude from S / ∈ dom ( γ ), S ′ = Γ ( S, γ ),and γ does not replace statements in parallel statements that S ′ = S . Simi-larly, if S = E ; E , also S = S ′ . Due to Lemma 1, ∃ ( S ′ , σ ′ ) op → ( E, σ ′ ) and σ = | { v ∈V| σ ( v )= σ ′ ( v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ . Due to the definition of live variables,we conclude that σ = | L ( E,V ) ∪L ( E,V ) σ ′ . If S is an if- or while-statement, we con-clude from S / ∈ dom ( γ ) and S ′ = Γ ( S, γ ) that S ′ is an if-/while-statement andthe condition is the same. Due to semantics, definition of live variable analysis,and σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ , we then conclude that ( S ′ , σ ′ ) op → ( E, σ ′ ) ∈ ex ( S ′ ) and σ = σ . Due to the definition of live variables, we conclude that σ = | L ( E,V ) ∪L ( E,V ) σ ′ . By definition, E = Γ ( E, γ ).Case 2 ( S = E ): Since replacements do not occur in parallel statementsand ¬∃ S s , S s : S s ∈ dom ( γ ) ∧ ( S = S s ; S s ∨ S = S s ), we conclude that ∃ S s , S s , S s , S s : S = S s ; S s ∧ S ′ = S s ; S s ∧ S s = Γ ( S s , γ ) ∧ S s = Γ ( S s , γ ) ∨ S = S s ∧ S ′ = S s ∧ S s = Γ ( S s , γ ) and either S s = S s or S s and S s are either both if-or both-while statements with the same condition and the if/else-body, the loopbody of S s is a replacement of the body of S s . First, consider the first case ( S s = S s ). Due to semantics, either (1) S = E ; S s and ( S s , σ ) op → ( E, σ ), (2) S = S s ∧ S s = E , σ = σ , and ( S, σ ) nop → ( S , σ ), or (3) S = S s ; S s and ( S s , σ ) op → ( S s , σ ). Due to Lemma 1, in case (1) ∃ ( S s , σ ′ ) op → ( E, σ ′ ) and σ ′ = σ ′ , and incase (3) ∃ ( S s , σ ′ ) op → ( S s , σ ′ ). Furthermore, σ = | { v ∈V| σ ( v )= σ ′ ( v ) ∨ op ≡ v := expr ; } σ ′ .Due to semantics, in case (1) ∃ ( S ′ , σ ′ ) op → ( E ; S s , σ ′ ), in case (2) ( S ′ , σ ′ ) nop → ( S s , σ ′ ), and in case (3) ∃ ( S ′ , σ ′ ) op → ( S s ; S s , σ ′ ). Since S s = S s = Γ ( S s , γ ), γ is only defined for subprograms of S and statements (thus, subprograms) canbe uniquely identified via labels, we get Γ ( S s , γ ) = S s . Hence, Γ ( S s ; S s , γ ) = S s ; Γ ( S s , γ ) = S s ; S s . Similarly, Γ ( E ; S s , γ ) = E ; Γ ( S s , γ ) = S s ; S s . Moreover, σ = | { v ∈V| σ ( v )= σ ′ ( v ) ∨ op ≡ v := expr ; } σ ′ ., σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ , and the definition of livevariable analyses let us conclude that σ = | L ( S ,V ) ∪L ( S ′ ,V ) σ ′ .Second, consider that ( S s = S s ). We know that S s and S s are either bothif- or both-while statements with the same condition and the if/else-body, theloop body of S s is a replacement of the body of S s . Due to semantics, definitionof live variable analysis, σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ , and the replacement function, we ocalized and Context-aware Checking of Functional Equivalence 27 then conclude that σ = σ and σ ′ = σ ′ and either S = S s and exists ( S ′ , σ ′ ) op → ( S ′ , σ ) ∈ ex ( S ′ ) with S ′ = Γ ( S , γ ) (due to S ; while expr do S is no subpro-gram of S) or S = S s ; S s and ( S ′ , σ ′ ) op → ( S ′ , σ ) ∈ ex ( S ′ ) with S ′ = Γ ( S , γ ).Due to the definition of live variables, we conclude that σ = | L ( S ,V ) ∪L ( S ′ ,V ) σ ′ . Corollary 2.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. For all ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) , if for all ≤ i < n not exists S s i , S s i such that ( S i = S s i ; S s i ∨ S i = S s i ) and S s i ∈ dom ( γ ) , then ∀ σ ′ ∈ Σ : σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ = ⇒ ∃ ( Γ ( S , γ ) , σ ′ ) op → . . . op n → ( Γ ( S n , γ ) , σ ′ n ) ∈ ex ( S ′ ) : ∀ ≤ i ≤ n : σ i = | L ( Si,V ) ∪L ( Γ ( Si,γ ) ,V ) σ ′ i .Proof. Proof by induction.
Base case (i=0): By definition ( S ′ , σ ) = ( Γ ( S, γ ) , σ ) ∈ ex ( S ′ ) for arbitrary σ ∈ Σ (including all σ ′ with σ = | L ( S,V ) ∪L ( S ′ ,V ) σ ′ ). Step case ( n − → n ): Due to Lemma 6, there exists ( Γ ( S, γ ) , σ ′ ) op → ( Γ ( S , γ ) , σ ′ ) with σ = | L ( S ,V ) ∪L ( S ′ ,V ) σ ′ . By induction, ( Γ ( S , γ ) , σ ′ ) op → . . . op n → ( Γ ( S n , γ ) , σ ′ n ) ∈ ex ( S ′ ) ∧ ∀ ≤ i ≤ n : σ i = | L ( Si,V ) ∪L ( Γ ( Si,γ ) ,V ) σ ′ i . By definition,the induction hypothesis follows. A.2 Auxiliary Lemmas for Soundness of Initialization andEqualization PartLemma 7.
Let ρ be a renaming function and V ⊆ V a subset of variables suchthat ∀ v ∈ V : ρ ( v ) = v ∨ ρ ( v ) / ∈ V . Then, ∀ σ ∈ Σ : ( init ( ρ, toSeq(V)) , σ ) → ∗ ( E, σ ′ ) = ⇒ ∀ v ∈ V : σ ′ ( v ) = σ ′ ( ρ ( v )) = σ ( ρ ( v )) .Proof. Proof by induction on the cardinality of V.
Base case ( | V | = 0 ) | V | = 0 implies V = ∅ , the hypothesis trivially holds. Step case ( | V | = n, n > ) Let toSeq( V ) = v , . . . , v n and σ ∈ Σ be arbi-trary. Then, init ( ρ, toSeq( V ) = init ( ρ, v , . . . , v n )) = v := ρ ( v ); init ( ρ, v , . . . , v n ) = v := ρ ( v ); init ( ρ, toSeq( V \ { v } )). Due to semantics, ( init ( ρ, toSeq(V)) , σ ) → ∗ ( E, σ ′ ) implies that ( init ( ρ, toSeq(V)) , σ ) v := ρ ( v ); → ( init ( ρ, toSeq( V \ { v } )) ,σ [ v := σ ( ρ ( v ))]) → ∗ ( E, σ ′ ). Thus, we get σ [ v := σ ( ρ ( v ))]( v ) = σ ( ρ ( v )) = σ [ v := σ ( ρ ( v ))]( ρ ( v )). By induction, ∀ v ∈ V \ { v } : σ ′ ( v ) = σ ′ ( ρ ( v )) = σ ( ρ ( v )). Since ∀ v ∈ V : ρ ( v ) = v ∨ ρ ( v ) / ∈ V and M ( ρ, toSeq( V \ { v } )) ⊆{ v , . . . , v n } , we get M ( ρ, toSeq( V \ { v } )) ∩ { v , ρ ( v ) } = ∅ . Due to Lemma 2, σ [ v := σ ( ρ ( v ))]( v ) = σ ′ ( v ) and σ [ v := σ ( ρ ( v ))]( ρ ( v )) = σ ′ ( ρ ( v )). Hence, σ ′ ( v ) = σ ′ ( ρ ( v )) = σ ( ρ ( v )). The induction hypothesis follows. Lemma 8.
Let ρ be a renaming function and V ⊆ V a subset of variables. Then, ∀ σ ∈ Σ : ( equal ( ρ, toSeq(V) , σ ) → ∗ ( E, σ ′ ) = ⇒ ∀ v ∈ V : σ ( v ) = σ ( ρ ( v )) .Proof. Proof by induction on the cardinality of V.
Base case ( | V | = 0 ) | V | = 0 implies V = ∅ , the hypothesis trivially holds. Step case ( | V | = n, n > ) Let toSeq( V ) = v , . . . , v n and σ ∈ Σ be arbi-trary. From definition, we conclude that equal ( ρ, toSeq( V ) = equal ( ρ, v , . . . , v n ) = assert ρ ( v ) == v ; equal ( ρ, v , . . . , v n ) = assert ρ ( v ) == v ; equal ( ρ, toSeq( V \{ v } )). Due to semantics and ( equal ( ρ, toSeq(V) , σ ) → ∗ ( E, σ ′ ), we infer that( equal ( ρ, toSeq(V) , σ ) ρ ( v )== v → ( equal ( ρ, toSeq( V \ { v } )) , σ ) → ∗ ( E, σ ′ ) and σ ( ρ ( v ) == v ) = true . Thus, σ ( ρ ( v )) = σ ( v ). By induction, ∀ v ∈ V \ { v } : σ ( v ) = σ ( ρ ( v )). The induction hypothesis follows. A.3 Proof of Theorem 1Theorem 1.
Let S and S be two (sub)programs. Given overapproximation UB ( S ) ⊆ U ⊆ V ( S ) and UB ( S ) ⊆ U ⊆ V ( S ) of the variables used beforedefinition and overapproximations M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ⊆ M ⊆V ( S ) of the modified variables, a renaming function ρ switch , and C ⊆ M ∪ M .If all ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C ) , σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C )) do not violate an assertion,then S ≡ V\ (( M ( S ) ∪M ( S )) \ C ) S .Proof. Let σ ∈ Σ , ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ), ( S , σ ) → ∗ ( E, σ ′′ ) ∈ ex ( S ),and u ∈ V \ (( M ( S ) ∪ M ( S )) \ C ) be arbitrary.Consider two cases. First, consider u ∈ V\ ( M ( S ) ∪M ( S )). Due to Lemma 2, σ ( u ) = σ ′ ( u ) and σ ( u ) = σ ′′ ( u ). Hence, σ ′ ( u ) = σ ′′ ( u ).Second, consider u ∈ ( M ( S ) ∪M ( S )) ∩ C . Let σ r ∈ Σ with σ r = | V ( S ∪M ( S σ and σ r = | V ( R ( S ,ρ switch)) ∪ S v ∈M ( S ρ switch( v ) ρ switch ( σ ). Due to definition of ρ switch such a data state exists.Due to semantics and Lemma 7, ∃ ( init ( ρ switch , ( U ∩ U ) ∩ ( M ∪ M )) , σ r ) → ∗ ( E, σ init ) with ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : σ init ( v ) = σ init ( ρ switch ( v )) = σ r ( ρ switch ( v )). By construction of σ r and ρ switch , we further get ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : σ r ( ρ switch ( v )) = ρ switch ( σ )( ρ switch ( v )) = σ ( ρ − ( ρ switch ( v ))) = σ ( v ). Due to Lemma 2 and M (( init ( ρ switch , ( U ∩ U ) ∩ ( M ∪ M ))) ⊆ ( U ∩ U ) ∩ ( M ∪ M ), we infer that ∀ v ∈ V \ (( U ∩ U ) ∩ ( M ∪ M )) : σ init ( v ) = σ r ( v ).Hence, σ r = σ init .Due to Lemma 4, there exists ( R ( S , ρ switch ) , ρ switch ( σ )) → ∗ ( E, ρ switch ( σ ′ )) ∈ ex ( R ( S , ρ switch )). By definition of σ r , and Lemma 1, there exists ( S , σ r ) → ∗ ( E, σ ′′ r ) ∈ ex ( S ) with σ ′′ = | V ( S ∪M ( S σ ′′ r and (( R ( S , ρ switch ) , σ r ) → ∗ ( E, σ ′ r ) ∈ ex (( R ( S , ρ switch )) with ρ switch ( σ ′ ) = | V ( R ( S ,ρ switch)) ∪ S v ∈M ( S ρ switch( v ) σ ′ r . Due toLemma 5, there exists ( R ( S , ρ switch ); S , σ r ) → ∗ ( E, σ c ) ∈ ex ( R ( S , ρ switch ); S )with σ c = | V ( R ( S ,ρ switch)) ∪ S v ∈M ( S ρ switch( v ) σ ′ r and σ c = | V ( S ∪M ( S σ ′′ r .Due to semantics , σ r = σ init , and all ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C ) , σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C ))do not violate assertions, there exists ( equal ( ρ switch , C ) , σ c ) → ∗ ( E, σ ′ c ). Due toLemma 8, we infer for all v ∈ C that σ c ( v ) = σ c ( ρ switch ( v )). Since u ∈ ( M ( S ) ∪M ( S )) ∩ C , we conclude that σ c ( ρ switch ( u )) = σ c ( u ) = σ ′′ r ( u ) = σ ′′ ( u ) and σ c ( ρ switch ( u )) = σ ′ r ( ρ switch ( u )) = ρ switch ( σ ′ )( ρ switch ( u )) = σ ′ ( ρ − ( ρ switch ( u ))) = σ ′ ( u ). ocalized and Context-aware Checking of Functional Equivalence 29 A.4 Proof of Theorem 2Lemma 9.
Let S and S be two (sub)programs, M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ⊆ M ⊆ V ( S ) overapproximations of the modified variables, ρ switch arenaming function , I = ( UB ( S ) ∩UB ( S )) ∩ ( M ∪ M ) , and C ⊆ M ∪ M . If all ( eq task ( S , S , ρ switch , I, C ) , σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( eq task ( S , S , ρ switch , I, C )) do not violate an assertion, then ∀ σ , σ ∈ Σ, V ⊆ V , v ∈ V \ (( M ( S ) ∪M ( S )) \ C ) : p = ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ) ∧ p = ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ) ∧UB ( p ) ∪ UB ( p ) ⊆ V ∧ σ = | V σ = ⇒ σ ′ ( v ) = σ ′ ( v ) .Proof. Let UB ( S ) ∪ UB ( S ) ⊆ V ⊆ V and u ∈ V \ (( M ( S ) ∪ M ( S )) \ C )be arbitrary. Furthermore, consider arbitrary p = ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S )and p = ( S , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ) with σ = | V σ .Consider two cases. First, consider u ∈ V \ ( M ( S ) ∪ M ( S )). Due toLemma 2, σ ( u ) = σ ′ ( u ) and σ ( u ) = σ ′ ( u ). Hence, σ ′ ( u ) = σ ′ ( u ).Second, consider u ∈ ( M ( S ) ∪ M ( S )) ∩ C . Let us consider σ r ∈ Σ with σ r = | ( UB ( S ∪UB ( S ∪M ( S ∪M ( S σ and σ r = | S v ∈ ( UB ( S ∪UB ( S ∪M ( S ∪M ( S ρ switch( v ) ρ switch ( σ ). Due to definition of ρ switch such a data state exists.Due to semantics and Lemma 7, there exists ( init ( ρ switch , ( UB ( S ) ∩UB ( S )) ∩ ( M ∪ M )) , σ r ) → ∗ ( E, σ init ) with ∀ v ∈ ( UB ( S ) ∩ UB ( S )) ∩ ( M ∪ M ) : σ init ( v ) = σ init ( ρ switch ( v )) = σ r ( ρ switch ( v )). By construction of σ r and ρ switch , UB ( S ) ∩ UB ( S ) ⊆ V ⊆ V , and σ = | V σ , we get ∀ v ∈ ( UB ( S ) ∩ UB ( S )) ∩ ( M ∪ M ) : σ r ( ρ switch ( v )) = ρ switch ( σ )( ρ switch ( v )) = σ ( ρ − ( ρ switch ( v ))) = σ ( v ) = σ ( v ). Due to Lemma 2 and M (( init ( ρ switch , ( UB ( S ) ∩UB ( S )) ∩ ( M ∪ M ))) ⊆ ( UB ( S ) ∩ UB ( S )) ∩ ( M ∪ M ), we infer that ∀ v ∈ V \ (( UB ( S ) ∩UB ( S )) ∩ ( M ∪ M )) : σ init ( v ) = σ r ( v ). Hence, σ r = σ init .Due to Lemma 4, there exists ( R ( S , ρ switch ) , ρ switch ( σ )) → ∗ ( E, ρ switch ( σ ′ )) ∈ ex ( R ( S , ρ switch )). By definition of σ r and Lemma 1, there exists execution( S , σ r ) → ∗ ( E, σ ′′ r ) ∈ ex ( S ) with σ ′ = | ( UB ( S ∪UB ( S ∪M ( S ∪M ( S σ ′′ r as wellas execution (( R ( S , ρ switch ) , σ r ) → ∗ ( E, σ ′ r ) ∈ ex (( R ( S , ρ switch )) such that ρ switch ( σ ′ ) = | S v ∈ ( UB ( S ∪UB ( S ∪M ( S ∪M ( S ρ switch( v ) σ ′ r . Due to Lemma 5, thereexists execution ( R ( S , ρ switch ); S , σ r ) → ∗ ( E, σ c ) ∈ ex ( R ( S , ρ switch ); S ) with σ c = | V ( R ( S ,ρ switch)) ∪ S v ∈M ( S ρ switch( v ) σ ′ r and σ c = | V ( S ∪M ( S σ ′′ r .Due to semantics, σ r = σ init , and all ( eq task ( S , S , ρ switch , UB ( S ) ∩UB ( S )) ∩ ( M ∪ M ) , C ) , σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( eq task ( S , S , ρ switch , ( UB ( S ) ∩ UB ( S )) ∩ ( M ∪ M ) , C )) do not violate assertions, there exists ( equal ( ρ switch , C ) , σ c ) → ∗ ( E, σ ′ c ). Due to Lemma 8, we infer for all v ∈ C that σ c ( v ) = σ c ( ρ switch ( v )).Since u ∈ ( M ( S ) ∪ M ( S )) ∩ C , we conclude that σ c ( ρ switch ( u )) = σ c ( u ) = σ ′′ r ( u ) = σ ′ ( u ) and σ c ( ρ switch ( u )) = σ ′ r ( ρ switch ( u )) = ρ switch ( σ ′ )( ρ switch ( u )) = σ ′ ( ρ − ( ρ switch ( u ))) = σ ′ ( u ). Theorem 2.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. If for all ( S , S ) ∈ γ thereexists M ( S ) ⊆ M ⊆ V ( S ) , M ( S ) ⊆ M ⊆ V ( S ) , L ( S , S, V ) ⊆ L ⊆ V , L ( S , S ′ , V ) ⊆ L ⊆ V , and renaming function ρ switch such that the equivalence task eq task ( S , S , ρ switch , ( UB ( S ) ∩UB ( S )) ∩ ( M ∪ M ) , ( M ∪ M ) ∩ ( L ∪ L )) does not violate an assertion, then S ≡ V S ′ .Proof. Consider ( S p , σ ) → ∗ ( E, σ ′ ) = ( S , σ ) op → . . . op n → ( S n , σ n ) be a pathfor an arbitrary program S p . We define the splitting of the path into m ≥ S p such that ∃ σ, σ ′ ∈ Σ : ( S, σ ) → ∗ ( S p , σ ′ ) if ( S p , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S p ), S ′ p = Γ ( S p , γ ), ∃ σ, σ ′ ∈ Σ : ( S ′ , σ ) → ∗ ( S ′ p , σ ′ ), σ ′′ ∈ Σ with σ = | L ( Sp,V ) ∪L ( S ′ p,V ) σ ′′ , and ( S ′ p , σ ′′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ), then σ ′ = | L ( E,V ) ∪L ( E,V ) σ ′′′ . Base case (m=0): Since m = 0, we conclude that S p = E . Since S ′ p = Γ ( S p , γ ) = Γ ( E, γ ), we conclude that S ′ p = E . Hence, σ ′ = σ ∧ σ ′′ = σ ′′′ . Byassumption σ = | L ( Sp,V ) ∪L ( S ′ p,V ) σ ′′ . Thus, the induction hypothesis follows. Step case ( m > S , σ ) op → . . . op i → ( S i , σ i ) be the first segment and σ ′ ∈ Σ be arbitrary such that σ = | L ( Sp,V ) ∪L ( S ′ p,V ) σ ′ and assume ( S ′ p , σ ′′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ). We know that S p = S and σ = σ . Consider two cases.First, assume that the first segment represents a sequence in which eachprogram of the first i-1 states does not start with a replaced subprogram. Dueto Corollary 2, there exists execution ( Γ ( S , γ ) , σ ′ ) op → . . . op i → ( Γ ( S i , γ ) , σ ′ i )with σ i = | L ( Si,V ) ∪L ( Γ ( Si,γ ) ,V ) σ ′ i . By assumption S ′ p = Γ ( S , γ ). By definition,( S i , σ i ) → ∗ ( E, σ ′ ) ∈ ex ( S i ), which consists of m − S . Due to semantics, semantics being deterministic, and ( S ′ p , σ ′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ), there exists (( Γ ( S i , γ ) , σ ′ i ) → ∗ ( E, σ ′′′ ) ∈ ex ( Γ ( S i , γ )). Fur-thermore, since S ′ p reachable from S ′ , S ′ p = Γ ( S , γ ), and ( Γ ( S , γ ) , σ ′ ) → ∗ ( Γ ( S i , γ ) , σ ′ i ), also Γ ( S i , γ ) reachable from S ′ . By induction, σ ′ = | L ( E,V ) ∪L ( E,V ) σ ′′′ . The induction hypothesis follows.Second, assume that the first segment is the execution of a subprogram S sp that will be replaced, i.e., S sp ∈ dom ( γ ) and S p = S = S sp ∧ S i = E ∨ S p = S = S sp ; S i . Furthermore, from S ′ p = Γ ( S p , γ ), we conclude that S ′ p = γ ( S sp ) = Γ ( S p , γ ) if S p = S = S sp and S ′ p = Γ ( S p , γ ) = Γ ( S sp , γ ); Γ ( S i , γ ) = γ ( S sp ); Γ ( S i , γ ) otherwise. Due to semantics, semantics being deterministic, and( S ′ p , σ ′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ), there exists ( S ′ p , σ ′ ) → ∗ ( S ′ i , σ ′ i ) ∈ ex ( S ′ p ) with S ′ i = Γ ( S i , γ ). Furthermore, there exists S ′ i → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ i ). We con-clude that ( Γ ( S sp , γ ) , σ ′ ) → ∗ ( E, σ ′ i ) (semantics). Due to the definitions of UB and L , UB ( S sp ) ∪ UB ( γ ( S sp )) ⊆ UB ( S p ) ∪ UB ( S ′ p ) ⊆ L ( S p ) ∪ L ( S ′ p ). Due toLemma 9, σ i = | (( L ( Sp,V ) ∪L ( S ′ p,V )) \ ( M ( Ssp ) ∪M ( γ ( Ssp )))) ∪ (( M ( Ssp ) ∪M ( γ ( Ssp )) ∩ ( L ∪ L σ ′ i . Bydefinition and S p reachable from S , L ( S i , V ) ⊆ L ( S, S sp , V ) ⊆ L . Similarly, L ( Γ ( S i , γ ) , V ) ⊆ L ( S ′ , γ ( S sp ) , V ) ⊆ L . We conclude from the definition of livevariables that σ i = | ( L ( Si,V ) ∪L ( S ′ i,V )) σ ′ i . By definition, ( S i , σ i ) → ∗ ( E, σ ′ ) ∈ ex ( S i ),which consists of m − S . Furthermore, we can ocalized and Context-aware Checking of Functional Equivalence 31 conclude from S ′ p reachable from S ′ , also Γ ( S i , γ ) reachable from S ′ . By induc-tion, σ ′ = | L ( E,V ) ∪L ( E,V ) σ ′′′ . The induction hypothesis follows.Let σ ∈ Σ , ( S, σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ), ( S ′ , σ ) → ∗ ( E, σ ′′ ) ∈ ex ( S ′ ), and u ∈ V be arbitrary. Since σ = | L ( S,V ) ∪L ( S ′ ,V ) σ , S ′ = Γ ( S, γ ), and ( S ′ , σ ) → ∗ ( E, σ ′′ ) ∈ ex ( S ′ ), the induction hypothesis gives us σ ′ = | L ( E,V ) ∪L ( E,V ) σ ′′ . Bydefinition of live variable analysis, u ∈ L ( E, V ). Hence, σ ′ ( u ) = σ ′′ ( u ). A.5 Proof of Theorem 3Lemma 10.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. If ¬∃ S s , S s : S s ∈ dom ( γ ) ∧ ( S = S s ; S s ∨ S = S s ) , then ∀ σ, σ ′ ∈ Σ : ( S, σ ) op → ( S , σ ) ∈ ex ( S ) ∧ σ = | L ( S ′ ,V ) σ ′ = ⇒ ∃ ( S ′ , σ ′ ) op → ( S ′ , σ ′ ) : S ′ = Γ ( S , γ ) ∧ σ = | L ( S ′ ,V ) σ ′ .Proof. Let S and S ′ be two programs, γ be a replacement function such that S ′ = Γ ( S, γ ) and ¬∃ S s , S s : S s ∈ dom ( γ ) ∧ ( S = S s ; S s ∨ S = S s ), V ⊆ V be aset of outputs and σ, σ ′ ∈ Σ with σ = | L ( S ′ ,V ) σ ′ .Assume p = ( S, σ ) op → ( S , σ ) ∈ ex ( S ). By definition, UB ( S ′ ) ⊆ L ( S ′ , V ).Consider two cases.Case 1 ( S = E ): Due to the semantics, we conclude that either S = E ; E ,or S is not a sequential composition, but a statement. If S is an assignment, anassertion or a parallel statement, we conclude from S / ∈ dom ( γ ), S ′ = Γ ( S, γ ),and γ does not replace statements in parallel statements that S ′ = S . Simi-larly, if S = E ; E , also S = S ′ . Due to Lemma 1, ∃ ( S ′ , σ ′ ) op → ( E, σ ′ ) and σ = | { v ∈V| σ ( v )= σ ′ ( v ) ∨∃ ≤ i ≤ n : opi ≡ v := expr ; } σ ′ . Due to the definition of live variables,we conclude that σ = | L ( E,V ) σ ′ . If S is an if- or while-statement, we concludefrom S / ∈ dom ( γ ) and S ′ = Γ ( S, γ ) that S ′ is an if-/while-statement and thecondition is the same. Due to semantics, definition of live variable analysis, and σ = | L ( S ′ ,V ) σ ′ , we then conclude that ( S ′ , σ ′ ) op → ( E, σ ′ ) ∈ ex ( S ′ ) and σ = σ .Due to the definition of live variables, we conclude that σ = | L ( E,V ) σ ′ . By defi-nition, E = Γ ( E, γ ).Case 2 ( S = E ): Since replacements do not occur in parallel statementsand ¬∃ S s , S s : S s ∈ dom ( γ ) ∧ ( S = S s ; S s ∨ S = S s ), we conclude that ∃ S s , S s , S s , S s : S = S s ; S s ∧ S ′ = S s ; S s ∧ S s = Γ ( S s , γ ) ∧ S s = Γ ( S s , γ ) ∨ S = S s ∧ S ′ = S s ∧ S s = Γ ( S s , γ ) and either S s = S s or S s and S s are either both if-or both-while statements with the same condition and the if/else-body, the loopbody of S s is a replacement of the body of S s . First, consider the first case ( S s = S s ). Due to semantics, either (1) S = E ; S s and ( S s , σ ) op → ( E, σ ), (2) S = S s ∧ S s = E , σ = σ , and ( S, σ ) nop → ( S , σ ), or (3) S = S s ; S s and ( S s , σ ) op → ( S s , σ ). Due to Lemma 1, in case (1) ∃ ( S s , σ ′ ) op → ( E, σ ′ ) and σ ′ = σ ′ , and incase (3) ∃ ( S s , σ ′ ) op → ( S s , σ ′ ). Furthermore, σ = | { v ∈V| σ ( v )= σ ′ ( v ) ∨ op ≡ v := expr ; } σ ′ .Due to semantics, in case (1) ∃ ( S ′ , σ ′ ) op → ( E ; S s , σ ′ ), in case (2) ( S ′ , σ ′ ) nop → ( S s , σ ′ ), and in case (3) ∃ ( S ′ , σ ′ ) op → ( S s ; S s , σ ′ ). Since S s = S s = Γ ( S s , γ ), γ is only defined for subprograms of S and statements (thus, subprograms) canbe uniquely identified via labels, we get Γ ( S s , γ ) = S s . Hence, Γ ( S s ; S s , γ ) = S s ; Γ ( S s , γ ) = S s ; S s . Similarly, Γ ( E ; S s , γ ) = E ; Γ ( S s , γ ) = S s ; S s . Moreover, σ = | { v ∈V| σ ( v )= σ ′ ( v ) ∨ op ≡ v := expr ; } σ ′ , σ = | L ( S ′ ,V ) σ ′ , and the definition of live vari-able analyses let us conclude that σ = | L ( S ′ ,V ) σ ′ .Second, consider that ( S s = S s ). We know that S s and S s are either both if-or both-while statements with the same condition and the if/else-body, the loopbody of S s is a replacement of the body of S s . Due to semantics, definition of livevariable analysis, σ = | L ( S ′ ,V ) σ ′ , and the replacement function, we then concludethat σ = σ and σ ′ = σ ′ and either S = S s and exists ( S ′ , σ ′ ) op → ( S ′ , σ ) ∈ ex ( S ′ ) with S ′ = Γ ( S , γ ) (due to S ; while expr do S is no subprogram of S)or S = S s ; S s and ( S ′ , σ ′ ) op → ( S ′ , σ ) ∈ ex ( S ′ ) with S ′ = Γ ( S , γ ). Due to thedefinition of live variables, we conclude that σ = | L ( S ′ ,V ) σ ′ . Corollary 3.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. For all ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) , if for all ≤ i < n not exists S s i , S s i such that ( S i = S s i ; S s i ∨ S i = S s i ) and S s i ∈ dom ( γ ) , then ∀ σ ′ ∈ Σ : σ = | L ( S ′ ,V ) σ ′ = ⇒∃ ( Γ ( S , γ ) , σ ′ ) op → . . . op n → ( Γ ( S n , γ ) , σ ′ n ) ∈ ex ( S ′ ) : ∀ ≤ i ≤ n : σ i = | L ( Γ ( Si,γ ) ,V ) σ ′ i .Proof. Proof by induction.
Base case (i=0): By definition ( S ′ , σ ) = ( Γ ( S, γ ) , σ ) ∈ ex ( S ′ ) for arbitrary σ ∈ Σ (including all σ ′ with σ = | L ( S ′ ,V ) σ ′ ). Step case ( n − → n ): Due to Lemma 10, there exists ( Γ ( S, γ ) , σ ′ ) op → ( Γ ( S , γ ) , σ ′ ) with σ = | L ( S ′ ,V ) σ ′ . By induction, ( Γ ( S , γ ) , σ ′ ) op → . . . op n → ( Γ ( S n , γ ) , σ ′ n ) ∈ ex ( S ′ ) : ∀ ≤ i ≤ n : σ i = | L ( Γ ( Si,γ ) ,V ) σ ′ i . By definition, theinduction hypothesis follows. Lemma 11.
Let S and S be two (sub)programs of programs S and S ′ , respec-tively. Consider arbitrary ( S, σ ) → ∗ ( S i , σ i ) → ∗ ( S j , σ j ) ∈ ex ( S ) and ( S ′ , σ ′ ) → ∗ ( S ′ i , σ ′ i ) → ∗ ( S ′ j , σ ′ j ) ∈ ex ( S ′ ) such that S i = S ∧ S j = E ∨ S i = S ; S j , S ′ i = S ∧ S ′ j = E ∨ S ′ i = S ; S ′ j , ( S , σ i ) → ∗ ( E, σ j ) ∈ ex ( S ) , and ( S , σ ′ i ) → ∗ ( E, σ ′ j ) ∈ ex ( S ) . Given overapproximations UB ( S ) ⊆ U ⊆ V ( S ) , UB ( S ) ⊆ U ⊆ V ( S ) and overapproximations M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ∪ { v ∈V | ∃ S → ∗ S ′ k v := aexpr → S ′ r ∈ syn P ( S ) } ⊆ M ⊆ V ( S ) of the modified variables,a renaming function ρ switch , and ( L ( S , S ′ , V )) ∩ ( M ∪ M ) ⊆ C ⊆ M ∪ M . Ifall executions ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C ) , σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C )) do not violate an assertion, V ⊆ V , and σ i = | L ( S ′ i,V ) σ ′ i , then σ j = | L ( S ′ j,V ) σ ′ j .Proof. Let u ∈ L ( S ′ j , V ) be arbitrary. In the following, we write v is assigned in p = ( S , σ ) op → . . . op n → ( S n , σ n ) ∈ ex ( S ) if ∃ i ∈ [1 , n ] : op i = v := aexpr ;.First, consider u / ∈ ( M ( S ) ∪ M ( S )) and σ i ( u ) = σ j ( u ). Due to Lemma 2, σ i ( u ) = σ j ( u ) and σ ′ i ( u ) = σ ′ j ( u ). Hence, σ j ( u ) = σ ′ j ( u ). ocalized and Context-aware Checking of Functional Equivalence 33 Second, consider u ∈ ( M ( S ) ∪ M ( S )) or σ i ( u ) = σ j ( u ). Let σ r ∈ Σ with σ r = | ( L ( S ′ i,V )) ∪M ( S ∪M ( S σ ′ i and σ r = | S v ∈ ( V ( S ∪M ( S ρ switch( v ) ρ switch ( σ i ). Due todefinition of ρ switch such a data state exists.Due to semantics and Lemma 7, ( init ( ρ switch , ( U ∩ U ) ∩ ( M ∪ M )) , σ r ) → ∗ ( E, σ init ) with ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : σ init ( v ) = σ init ( ρ switch ( v )) = σ r ( ρ switch ( v )). By construction of σ r and ρ switch , and σ i = | L ( S ′ i,V ) σ ′ i , we get ∀ v ∈ ( L ( S ′ i , V )) : σ r ( ρ switch ( v )) = ρ switch ( σ i )( ρ switch ( v )) = σ i ( ρ − ( ρ switch ( v ))) = σ i ( v ) = σ ′ i ( v ). Due to Lemma 2 and modifications M (( init ( ρ switch , ( U ∪ U ) ∩ ( M ∪ M )))) ⊆ ( U ∩ U ) ∩ ( M ∪ M ), we infer that ∀ v ∈ V \ (( U ∩ U ) ∩ ( M ∪ M )) : σ init ( v ) = σ r ( v ). Hence, σ ′ i = | L ( S ′ i,V ) σ init and σ init = | S v ∈ ( V ( S ∪M ( S ρ switch( v ) ρ switch ( σ i ).Due to Lemma 4, there exists ( R ( S , ρ switch ) , ρ switch ( σ i )) → ∗ ( E, ρ switch ( σ j )) ∈ ex ( R ( S , ρ switch )). Since σ ′ i = | L ( S ′ i,V ) σ init , by definition UB ( S ) ⊆ L ( S ′ i , V ),and σ init = | S v ∈ ( V ( S ∪M ( S ρ switch( v ) ρ switch ( σ i ), we infer from Lemma 1 that ∃ p ′ = ( S , σ init ) → ∗ ( E, σ ′′ r ) ∈ ex ( S ) with σ ′ j = | L ( S ′ i,V )) ∪{ v ∈V| v assigned in p ′} σ ′′ r and ∃ p = ( R ( S , ρ switch ) , σ init ) → ∗ ( E, σ ′ r ) ∈ ex ( R ( S , ρ switch )) such that ρ switch ( σ j )= | S v ∈ ( V ( S ∪M ( S ρ switch( v ) σ ′ r . Due to Lemma 5, ∃ ( R ( S , ρ switch ); S , σ init ) → ∗ ( E, σ c ) ∈ ex ( R ( S , ρ switch ); S ) with σ c = | V ( R ( S ,ρ switch)) ∪ S v ∈M ( S ρ switch( v ) σ ′ r and σ c = | V ( S ∪M ( S σ ′′ r .Due to semantics and all ( eq task ( S , S , ρ switch , U ∩ U ∩ ( M ∪ M ) , C ) , σ ) → ∗ ( S ′ , σ ′ ) ∈ ex ( eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , C )) do not violateassertions, there exists ( equal ( ρ switch , C ) , σ c ) → ∗ ( E, σ ′ c ). Due to Lemma 8, weinfer for all v ∈ C that σ c ( v ) = σ c ( ρ switch ( v )).Distinguish two cases. First, consider u ∈ ( M ( S ) ∪ M ( S )). We concludethat u ∈ C . Hence, σ c ( u ) = σ c ( ρ switch ( u )). By definition of L , we conclude that u ∈ L ( S ′ i , V ) or u is assigned on ( S , σ ′ i ) → ∗ ( E, σ ′ j ) ∈ ex ( S ). Due to Lemma 1,we infer that u ∈ L ( S ′ i , V ) or u is assigned on p ′ . We conclude that σ c ( u ) = σ ′′ r ( u ) = σ ′ j ( u ) and σ c ( ρ switch ( u )) = σ ′ r ( ρ switch ( u )) = ρ switch ( σ j )( ρ switch ( u )) = σ j ( ρ − ( ρ switch ( u )) = σ j ( u ). Since σ c ( u ) = σ c ( ρ switch ( u )), we get σ ′ j ( u ) = σ j ( u ).Second, consider σ j ( u ) = σ ′ j ( u ) and u / ∈ ( M ( S ) ∪ M ( S )). Since u ∈L ( S ′ j , V ) and σ i ( u ) = σ j ( u ), we conclude that u / ∈ L ( S ′ i , V ). By definition of L , we conclude that u is assigned on ( S , σ ′ i ) → ∗ ( E, σ ′ j ) ∈ ex ( S ). Hence, u ∈ M and, therefore, u ∈ C . Then, due to Lemma 1, u is assigned on p ′ .Furthermore, we conclude that σ c ( u ) = σ ′′ r ( u ) = σ ′ j ( u ) and σ c ( ρ switch ( u )) = σ ′ r ( ρ switch ( u )) = ρ switch ( σ j )( ρ switch ( u )) = σ j ( ρ − ( ρ switch ( u )) = σ j ( u ). Since u ∈ C , we conclude that σ ′ j ( u ) = σ c ( u ) = σ c ( ρ switch ( u )) = σ j ( u ). Theorem 3.
Let S and S ′ be two programs, γ be a replacement function suchthat S ′ = Γ ( S, γ ) , and V ⊆ V be a set of outputs. If for all ( S , S ) ∈ γ there exists overapproximations UB ( S ) ⊆ U ⊆ V ( S ) , UB ( S ) ⊆ U ⊆ V ( S ) , M ( S ) ⊆ M ⊆ V ( S ) , M ( S ) ∪ { v ∈ V | ∃ S → ∗ S k v := aexpr → S r ∈ syn P ( S ) } ⊆ M ⊆ V ( S ) , L ( S , S, V ) ⊆ L ⊆ V , L ( S , S ′ , V ) ⊆ L ⊆ V , and renaming ρ switch s.t. eq task ( S , S , ρ switch , ( U ∩ U ) ∩ ( M ∪ M ) , ( M ∪ M ) ∩ ( L ∪ L )) does not violate an assertion, then S ≡ V S ′ .Proof. Consider ( S p , σ ) → ∗ ( E, σ ′ ) = ( S , σ ) op → . . . op n → ( S n , σ n ) be a pathfor an arbitrary program S p . We define the splitting of the path into m ≥ S p such that ∃ σ, σ ′ ∈ Σ : ( S, σ ) → ∗ ( S p , σ ′ ) if ( S p , σ ) → ∗ ( E, σ ′ ) ∈ ex ( S p ), S ′ p = Γ ( S p , γ ), ∃ σ, σ ′ ∈ Σ : ( S ′ , σ ) → ∗ ( S ′ p , σ ′ ), σ ′′ ∈ Σ with σ = | L ( S ′ p,V ) σ ′′ , and ( S ′ p , σ ′′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ), then σ ′ = | L ( E,V ) σ ′′′ . Base case (m=0): Since m = 0, we conclude that S p = E . Since S ′ p = Γ ( S p , γ ) = Γ ( E, γ ), we conclude that S ′ p = E . Hence, σ ′ = σ ∧ σ ′′ = σ ′′′ . Byassumption σ = | L ( S ′ p,V ) σ ′′ . Thus, the induction hypothesis follows. Step case ( m > S , σ ) op → . . . op i → ( S i , σ i ) be the first segment and σ ′ ∈ Σ be arbitrary such that σ = | L ( S ′ p,V ) σ ′ and assume ( S ′ p , σ ′′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ). We know that S p = S and σ = σ . Consider two cases.First, assume that the first segment represents a sequence in which eachprogram of the first i-1 states does not start with a replaced subprogram. Dueto Corollary 3, there exists execution ( Γ ( S , γ ) , σ ′ ) op → . . . op i → ( Γ ( S i , γ ) , σ ′ i ) with σ i = | L ( Γ ( Si,γ ) ,V ) σ ′ i . By assumption S ′ p = Γ ( S , γ ). By definition, ( S i , σ i ) → ∗ ( E, σ ′ ) ∈ ex ( S i ), which consists of m − S .Due to semantics, semantics being deterministic, and ( S ′ p , σ ′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ), there exists (( Γ ( S i , γ ) , σ ′ i ) → ∗ ( E, σ ′′′ ) ∈ ex ( Γ ( S i , γ )). Furthermore,since S ′ p reachable from S ′ , S ′ p = Γ ( S , γ ), and ( Γ ( S , γ ) , σ ′ ) → ∗ ( Γ ( S i , γ ) , σ ′ i ),also Γ ( S i , γ ) reachable from S ′ . By induction, σ ′ = | L ( E,V ) σ ′′′ . The inductionhypothesis follows.Second, assume that the first segment is the execution of a subprogram S sp that will be replaced, i.e., S sp ∈ dom ( γ ) and S p = S = S sp ∧ S i = E ∨ S p = S = S sp ; S i ∧ ( S sp , σ ) → ∗ ( E, σ i ) ∈ ex ( S sp ). Furthermore, from S ′ p = Γ ( S p , γ ), we conclude that S ′ p = γ ( S sp ) = Γ ( S p , γ ) if S p = S = S sp and S ′ p = Γ ( S p , γ ) = Γ ( S sp , γ ); Γ ( S i , γ ) = γ ( S sp ); Γ ( S i , γ ) otherwise. Due to seman-tics, semantics being deterministic, and ( S ′ p , σ ′ ) → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ p ), thereexists ( S ′ p , σ ′ ) → ∗ ( S ′ i , σ ′ i ) ∈ ex ( S ′ p ) with S ′ i = Γ ( S i , γ ) and ( γ ( S sp ) , σ ′ ) → ∗ ( E, σ ′ i ). Furthermore, there exists S ′ i → ∗ ( E, σ ′′′ ) ∈ ex ( S ′ i ). We conclude that( Γ ( S sp , γ ) , σ ′ ) → ∗ ( E, σ ′ i ) (semantics). Due to Lemma 11, σ i = | L ( S ′ i,V ) σ ′ i . Bydefinition, ( S i , σ i ) → ∗ ( E, σ ′ ) ∈ ex ( S i ), which consists of m − S . Furthermore, we can conclude from S ′ p reachable from S ′ ,also Γ ( S i , γ ) reachable from S ′ . By induction, σ ′ = | L ( E,V ) σ ′′′ . The inductionhypothesis follows.Let σ ∈ Σ , ( S, σ ) → ∗ ( E, σ ′ ) ∈ ex ( S ), ( S ′ , σ ) → ∗ ( E, σ ′′ ) ∈ ex ( S ′ ), and u ∈ V be arbitrary. Since σ = | L ( S ′ ,V ) σ , S ′ = Γ ( S, γ ), and ( S ′ , σ ) → ∗ ( E, σ ′′ ) ∈ ocalized and Context-aware Checking of Functional Equivalence 35 ex ( S ′ ), the induction hypothesis gives us σ ′ = | L ( E,V ) σ ′′ . By definition of livevariable analysis, u ∈ L ( E, V ). Hence, σ ′ ( v ) = σ ′′ ( v ). A.6 Correctness of ρ switch Lemma 12.
Let S and S be two (sub)programs. Given overapproximation UB ( S ) ⊆ U ⊆ V ( S ) and UB ( S ) ⊆ U ⊆ V ( S ) of the variables used be-fore definition and overapproximations M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ⊆ M ⊆ V ( S ) of the modified variables. Any function ρ switch is appropriate forrenaming and ensures ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : ρ switch ( v ) = v ∨ ρ switch ( v ) / ∈ ( U ∩ U ) ∩ ( M ∪ M ) .Proof. Let switch : M ∪ M → V \ ( V ( S ) ∪ V ( S )) be an arbitrary injectivefunction. Due to injectivity of function switch and the construction of ρ switch ,function ρ switch is bijective.Since M ( S ) ⊆ M ⊆ V ( S ) and by definition of ρ switch for all v ∈ V ( S )either ρ switch ( v ) = v and v / ∈ M ∪ M or ρ switch ( v ) ∈ V \ ( V ( S ) ∪ V ( S )), weinfer ∀ v ∈ V ( S ) ∪ M ( S ) : ρ ( v ) / ∈ M ( S )Since M ( S ) ⊆ M and for all v ∈ M ∪ M renamed variable ρ switch ( v ) ∈V \ ( V ( S ) ∪ V ( S )), we infer ∀ v ∈ M ( S ) : ρ ( v ) / ∈ V ( S ) ∪ M ( S ).We conclude that ρ switch is appropriate for renaming.By definition, ( U ∩ U ) ∩ ( M ∪ M ) ⊆ U ∩ U ⊆ V ( S ) ∪ V ( S ). Byconstruction of ρ switch , for all v ∈ V ( S ) ∪ V ( S ) either ρ switch ( v ) = v or ρ switch ( v ) / ∈ V ( S ) ∪ V ( S ). Hence, ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : ρ switch ( v ) = v ∨ ρ switch ( v ) / ∈ ( U ∩ U2
Let S and S be two (sub)programs. Given overapproximation UB ( S ) ⊆ U ⊆ V ( S ) and UB ( S ) ⊆ U ⊆ V ( S ) of the variables used be-fore definition and overapproximations M ( S ) ⊆ M ⊆ V ( S ) and M ( S ) ⊆ M ⊆ V ( S ) of the modified variables. Any function ρ switch is appropriate forrenaming and ensures ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : ρ switch ( v ) = v ∨ ρ switch ( v ) / ∈ ( U ∩ U ) ∩ ( M ∪ M ) .Proof. Let switch : M ∪ M → V \ ( V ( S ) ∪ V ( S )) be an arbitrary injectivefunction. Due to injectivity of function switch and the construction of ρ switch ,function ρ switch is bijective.Since M ( S ) ⊆ M ⊆ V ( S ) and by definition of ρ switch for all v ∈ V ( S )either ρ switch ( v ) = v and v / ∈ M ∪ M or ρ switch ( v ) ∈ V \ ( V ( S ) ∪ V ( S )), weinfer ∀ v ∈ V ( S ) ∪ M ( S ) : ρ ( v ) / ∈ M ( S )Since M ( S ) ⊆ M and for all v ∈ M ∪ M renamed variable ρ switch ( v ) ∈V \ ( V ( S ) ∪ V ( S )), we infer ∀ v ∈ M ( S ) : ρ ( v ) / ∈ V ( S ) ∪ M ( S ).We conclude that ρ switch is appropriate for renaming.By definition, ( U ∩ U ) ∩ ( M ∪ M ) ⊆ U ∩ U ⊆ V ( S ) ∪ V ( S ). Byconstruction of ρ switch , for all v ∈ V ( S ) ∪ V ( S ) either ρ switch ( v ) = v or ρ switch ( v ) / ∈ V ( S ) ∪ V ( S ). Hence, ∀ v ∈ ( U ∩ U ) ∩ ( M ∪ M ) : ρ switch ( v ) = v ∨ ρ switch ( v ) / ∈ ( U ∩ U2 ) ∩ ( M ∪ M2