Data Flow Analysis —Applications (I)
Preliminaries of Data Flow Analysis
Input and Output States
- Each execution of an IR statement transforms an input state to a new output state Input and Output States
- The input (output) state is associated with the program point before (after) the statement
- Data-flow analysis is to find a solution to a set of safe-approximation-directed constraints on the IN[s]’s and OUT[s]’s, for all statements s.
- constraints based on semantics of statements (transfer functions)
- constraints based on the flows of control
Notations for Transfer Function’ s Constraints
- Forward Analysis
- O U T [ s ] = f s ( I N [ s ] ) OUT[s] = f_s(IN[s]) OUT[s]=fs(IN[s])
- Backward Analysis
- I N [ s ] = f s ( O U T [ s ] ) IN[s] = f_s(OUT[s]) IN[s]=fs(OUT[s])
Notations for Control Flow’ s Constraints
(I) Reaching Definitions Analysis
Reaching Definitions
A definition d at program point p reaches a point q if there is a path from p to q such that d is not “killed” along that path
- A definition of a variable v is a statement that assigns a value to v
- Translated as: definition of variable v at program point p reaches point q if there is a path from p to q such that no new definition of v appears on that path
- Reaching definitions can be used to detect possible undefined variables.
Understanding Reaching Definitions
- Data Flow Values/Facts
- The definitions of all the variables in a program
- Can be represented by bit vectors
This statement “generates” a definition D of variable v and “kills” all the other definitions in the program that define variable v, while leaving the remaining incoming definitions unaffected
-
Transfer Function
-
O U T [ B ] = g e n B ∪ ( I N [ B ] − k i l l B ) OUT[B] = gen_B \cup (IN[B] - kill_B) OUT[B]=genB∪(IN[B]−killB)
-
-
Control Flow
- I N [ B ] = ∪ P a p r e d e c e s s o r o f B O U T [ P ] IN[B] = \cup_{P \, a\, predecessor \,of \,B} OUT[P] IN[B]=∪PapredecessorofBOUT[P]
Algorithm of Reaching Definitions Analysis
INPUT: CFG( k i l l B kill_B killB and g e n B gen_B genB computed for each basic block B)
OUTPUT: IN[B] and OUT[B] for each basic block B
METHOD:
Why this iterative algorithm can finally stop?
Because O U T [ S ] OUT[S] OUT[S] never shrinks
Safe to terminate by this condition?
IN’ S and OUT’ S will not change
Reach a fixed point Also related with monotonicity (next lectures)