# Reaching definition

In compiler theory, a reaching definition for a given instruction is an earlier instruction whose target variable can reach (be assigned to) the given one without an intervening assignment. For example, in the following code:

d1 : y := 3
d2 : x := y


d1 is a reaching definition for d2. In the following, example, however:

d1 : y := 3
d2 : y := 4
d3 : x := y


d1 is no longer a reaching definition for d3, because d2 kills its reach: the value defined in d1 is no longer available and cannot reach d3.

## As analysis

The similarly named reaching definitions is a data-flow analysis which statically determines which definitions may reach a given point in the code. Because of its simplicity, it is often used as the canonical example of a data-flow analysis in textbooks. The data-flow confluence operator used is set union, and the analysis is forward flow. Reaching definitions are used to compute use-def chains and def-use chains.

The data-flow equations used for a given basic block ${\displaystyle S}$ in reaching definitions are:

• ${\displaystyle {\rm {REACH}}_{\rm {in}}[S]=\bigcup _{p\in pred[S]}{\rm {REACH}}_{\rm {out}}[p]}$
• ${\displaystyle {\rm {REACH}}_{\rm {out}}[S]={\rm {GEN}}[S]\cup ({\rm {REACH}}_{\rm {in}}[S]-{\rm {KILL}}[S])}$

In other words, the set of reaching definitions going into ${\displaystyle S}$ are all of the reaching definitions from ${\displaystyle S}$'s predecessors, ${\displaystyle pred[S]}$. ${\displaystyle pred[S]}$ consists of all of the basic blocks that come before ${\displaystyle S}$ in the control flow graph. The reaching definitions coming out of ${\displaystyle S}$ are all reaching definitions of its predecessors minus those reaching definitions whose variable is killed by ${\displaystyle S}$ plus any new definitions generated within ${\displaystyle S}$.

For a generic instruction, we define the ${\displaystyle {\rm {GEN}}}$ and ${\displaystyle {\rm {KILL}}}$ sets as follows:

• ${\displaystyle {\rm {GEN}}[d:y\leftarrow f(x_{1},\cdots ,x_{n})]=\{d\}}$
• ${\displaystyle {\rm {KILL}}[d:y\leftarrow f(x_{1},\cdots ,x_{n})]={\rm {DEFS}}[y]-\{d\}}$

where ${\displaystyle {\rm {DEFS}}[y]}$ is the set of all definitions that assign to the variable ${\displaystyle y}$. Here ${\displaystyle d}$ is a unique label attached to the assigning instruction; thus, the domain of values in reaching definitions are these instruction labels.