![]() | ![]() | ![]() | The Reaching Definitions Problem |
This can get tricky. In the example program, for instance, we somehow have to arrange to use the same temporary to hold z/n when evaluated before the loop and at the end of the loop.
This puts more constraints on the code generator than necessary. In the example, there is no reason to put the result of the first instance of y*z in the same location as the result of the instance used for the while loop boolean. Only the value produced for the boolean is used to eliminate evaluation of a redundant CSE.
< p1 > x := exp < p2 >
REACHING(p2) = ( REACHING(p1) + { GEN(exp) } -
{ other instances of GEN(exp) } - KILL(x))
< p0 > | if exp | then | < p1 > stmt1 < p3 > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
else | < p2 > stmt2 < p4 > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end < p5 > |
REACHING( p5 ) = REACHING( p3 ) U REACHING( p4 )
REACHING( p1 ) = REACHING( p2 ) = REACHING( p0 ) -
{ other instances of subexpressions of exp } + { GEN(exp) }
< p0 > | while < p1 > | exp do | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
< p2 > stmt < p3 > | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end < p4 > |
REACHING( p1 ) = ( REACHING( p0 ) U REACHING( p3 ))
REACHING( p2 ) = REACHING( p4 ) = REACHING( p1 ) -
{ other instances of subexpressions of exp } + { GEN(exp) }
![]() | ![]() | ![]() | The Reaching Definitions Problem |