Analysis of Pointers and Structure
Analysis of Pointers and Structure
David R. Chase*
Mark Wegmanl
F. Kenneth Zadeckj
297
not certain, that X and W.cdr point to cells that are abased. places probably are going to be treated differently, while all
In fact, inspection of the program reveals that X and U.&r nodes allocated at a given place will probably be updated
always point to the same cell at this location, and the data similarly.
structure is in fact a list, but here the SSG does not provide
that much information. In Section 4.3 we show how to obtain 3.1 The Simple Fixed-Point Algorithm
that information. The initial, optimistic approximation for a statement’s SSG
is the graph containing all the nodes allocated in the pro-
1 Y + nil gram, but with no edges leaving any of them. So, each SSG
2 while (.. .> is originally identical with the same set of nodes. The most
3 X + cons() conservative approximation (and the one containing the least
information) is the graph with all possible edges (this is
4 x.car <- 1
the complete graph, except that edges cannot be directed
5 x.cdr .- w from fields to variable nodes). The analysis proceeds by
6 W + cons0 adding edges to the SSGs, and its goal is to find the SSG
7 Y.car ‘- 2 with the smallest number of edges that is still a conservative
8 w.cdr s- x approximation to the actual storage; i.e., the SSG that has
1
9 end every edge it needs, but no more.
nil The algorithm presented here is a modification of Weg-
10 Z+W
/ breit’s iterative data flow analysis technique [Weg75]. We
11 while (. , .>
12 Y 6 z.cdr start out with a worklist that is initialized to contain the
13 entry statement in the program. At each step we take a
z + Y,cdr
statement off the worklist and attempt to evaluate it. If the
14 end
statement can be evaluated and some new edges are added
to its SSG, we put the successors of the statement onto
Figure 2. Twccelement alternating list and its SSG after the worklist. The algorithm terminates when the worklist
Statement 8. becomes empty.
If the statement is a join point in the program (i.e., if
The following three operations are the only ways to two or more statements have this statement as a successor),
construct an SSG: (1) nodes may be added, (2) edges may then each node in the SSG entering this statement will have,
be added or (3) nodes may be merged. When two nodes are as its edge set, the union of the edge sets for the correspond-
merged, all edges pointing into either of them point into the ing nodes in the SSGs for the predecessor statements.
merged node and, field by field, all edges pointing out of If the right hand side of an assignment is a variable X,
them must point out of the merged node. the r-value is the set of nodes reached by edges leaving X.
If the right hand side of an assignment is a field X.cdr, the
3 The Simple Algorithm r-value is the set of nodes reached by edges leaving fields in
I-ualue(X.cdr). halue(X.A) is the set of fields labeled A in
In our simple algorithm, all SSGs for a program contain the
nodes reached by edges leaving the variable X, as shown in
same set of nodes: one node for each simple variable (variable
Figure 3. If the right hand side of a statement is a cons, the
nodes) and one node for each statement in the program that
allocates a data structure, such as new in Pascal and cons r-value is the heap node corresponding to that statement.
in Lisp (heap nodes). A naive representation of the graphs
built for a pro,;ram of S statements will contain S SSGs,
and each of these will contain O(S f V) nodes, for a total of
0X 1 l-value@. cdr) (a set of fields)
298
of type schemes is to detect errors at compile time, they have instances are merged as soon as they become uninteresting.
also been used by compilers for simple alias analysis. The We use the cons statement to generate new instances and
idea is that a modification to one type of structure cannot the assignment statements and meet operations to merge
be applied to a structure with a different type. If a pointer instances. We still require that only instances of the same
can point to only one type, then an update from that pointer cons statement can be merged together. There can be
cannot modify any objects of different type. at most as many SSG nodes with deterministic variables
In a language like Pascal, each type corresponds to a pointing into them as there are variables in the program. For
disjoint set of nodes. The set of nodes corresponds to the each cons statement there can be at most one instance not
locations at which a type can be allocated. An allocate pointed to by a deterministic variable. We call this instance
statement in Pascal takes a pointer as an argument; since the summary node. Thus, the total number of nodes in any
a pointer can point to only one type, the set of nodes is SSG is bounded by the sum of the number of allocation
disjoint. The problem we face in designing a pointer analysis statements and the number of variables.
scheme is choosing which nodes to merge and which not to Variables can change their values at two places: sssign-
merge. By choosing to merge only nodes that come from the ments and join points. At these points, an SSG node that
same allocation site, we do not merge nodes that would (or no longer is pointed to by a variable becomes uninteresting
could) be given different type declarations. and the SSG node may be merged.
In Pascal, a declaration limits the number of different
types a pointer can point to, and compile time analysis 4.1.1 Merging After Assignments
checks that they cannot point to additional types. In our An SSG node n becomes uninteresting after an assign-
algorithm, we discover at compile time the set of nodes a ment statement s assigning to variable V if (1) before evalu-
given pointer can point to. Any program that would cause ation of s, V was a deterministic variable pointing to n and
our algorithm to add an edge in the SSG between a node (2) after evaluation of s, no deterministic variable points to
within the set for one type to a node of a type which it cannot It.
point to would be flagged as an error by a Pascal compiler. If n has just become uninteresting and there are any
Thus, if at the end of our analysis, all nodes of a given type other uninteresting instances of the cons statement of which
were merged, there would be no more edges between them n is an instance, they are merged.
than those specified by a Pascal type declaration.
Type declarations often give a good description of the 4.1.2 Merging At Join Points
shape of data structures. Our SSGs differ principally in that The meet operation is performed at any join point in the
there is a different SSG for each statement in a program, and program. A very naive meet would union the sets of nodes
it would be impractical to have the programmer include new from the entering SSGs and fix up the variables to point to
declarations of types for each statement. the union of the nodes they pointed to in the entering SSGs.
Unfortunately, this meet is unacceptable, since the number
4 Extensions to the Simple Algorithm of nodes in the SSGs will grow without bound. Therefore,
SSG nodes must be merged when performing the meet.
In this section, we present several synergistic extensions to
Our goals in constructing this merging scheme are:
the simple algorithm: allowing more than one SSG node
to be kept per allocation statement (Section 4.1); allowing 1. The number of SSG nodes is bounded. In particular,
strong update to be done to SSG nodes in certain cases at the end of the merge, there is at most one instance
(Section 4.2); and associating reference counts with the SSG of a cons statement without a deterministic variable
nodes to allow us, for example, to detect tree-like structures pointing to it.
(Section 4.3).
2. The largest number of deterministic variables are pre-
4.1 Maintaining MultipIe Instances of a served.
cons Node
In the simple algorithm (Section 3), we assumed that the 3. As few edges as possible are added to the graph.
SSGs contain only one node for each cons statement. While 4. The matching can be performed efficiently.
we can distinguish structures composed of elements allocated
at different cons statements, we need additional detail to 5. Preserve information can be used to perform strong
determine other information. We cannot deduce that the updates to fields (see Section 4.2).
data structure is acyclic, and thus the cons cells pointed to
by X on different iterations of the loop are always different. We wish to form a meet between the two SSGs in
Our solution is to allow SSGs to contain multiple nodes Figure 4, and we wish to choose the “best” merge. The
from a single cons statement. Each of these nodes is called choice in Figure 5 is unacceptable both because general ap-
an instance of that cons statement. The execution of a cons plication of this strategy leads to unbounded graph growth,
statement causes a new instance to be created, and a pointer and because all variables are made non-deterministic. The
to that instance is assigned to the target of the left hand side two choices in Figures 6 and 7 are better, but without
of the assignment statement. additional information an arbitrary choice must be made.
A natural question is, “How many instances are Figure 6 keeps X and Y deterministic, while Figure 7 keeps
enough?” The answer depends on the context. What is Z deterministic. One way to choose is to impose an order
desired is to keep only the interesting instances. on the variables and always perform SSG node merges in
We classify variables into two categories: (1) a deter- the same (variable-by-variable) order. Another choice is to
ministic variable points to one SSG node and may possibly give up, and use Figure 8. We suggest another heuristic,
point to nil, and (2) a non-deterministic variable points to however, that we believe is more appropriate.
more than one SSG node. Being deterministic is an impor- At a join point at which SSG nodes are being merged,
tant property for variables to have. Section 4.2 exploits this psuedo-assignments (&functions) are also inserted for vari-
property to perform strong update. ables. The variables that deterministically reference SSG
We call an SSG node interesting if it is pointed to by a nodes at the CFG predecessors can be separated into those
deterministic variable. We apply the rule that uninteresting that are arguments of &functions at the join point and those
299
Figure 6 results if X and Y are not involved in psuedo-
X- X assignments but Z is; X and Y remain deterministic, but
Z becomes non-deterministic. Figure 7 results if Z is not
Y- Y
involved in a psuedo-assignment. Figure 8 results if all three
variables are involved in a psuedo-assignment.
The second step examines any SSG nodes pointed to by
z/ Z deterministic variables not paired by the first step; that is,
5i % those that occur in d-functions. Ignoring non-deterministic
variables, two SSG nodes “left and n,.ight allocated
Fx
at the
Figure 4. Two graphs to merge. same statement may be paired up if the sets of variables5
referencing nl,jt and nright are identical. If the sets of
variables are not identical, but the differing variables do
not point to any node in the other SSG (that is, they are
wr Y nil, atom, or empty), then the two nodes may be paired up.
For example (or as a special case), if a variable is the sole
reference to a node n in one SSG and nil in the other SSG,
Z then n is not merged into its corresponding summary node.
After all those SSG nodes have been paired up and
merged, all the remaining SSG nodes are merged into their
Figure 5. A large, unacceptable merge. summary nodes on a per-statement basis.
The above merging conditions ensure that only one
instance of an allocation site’s nodes is not referenced by
any deterministic variables (that is, in any SSG there can be
at most one cons instance for each variable and one cons
instance for each statement). This does not imply that
the number of instances cannot grow at the merge point.
Consider the example in Figure 9. As the loop (a join
point) is entered from above, both X and Y are redefined
in &functions. In the SSG transmitted from the preceding
statements, X addresses a cons node (call it nl) and Y is nil.
Figure 6. X and Y remain deterministic. In the SSG transmitted from the end of the loop, X is nil
and Y addresses a cons node (call it nz). Should nl and nl
be paired up, merged into a summary for their allocation
statement, or left separate? By the meet given above,
they remain separate, even though both nodes model the
same run-time location. This is counterintuitive but correct,
because at the top of the loop X and Y never simultaneously
refer to the same address (unless it is nil).
X + cons0
Y + nil
Figure 7. Z remains deterministic.
while0
Y+X
X
X + nil
end
Y
Figure 9. Program in which the number of instances after
Z % the join is greater than before the join.
300
corresponds, on all execution paths, to at most one location block temporarily. In some cases, it is not possible to
in the heap. If our algorithm cannot guarantee that both evaluate the l-value of a statement of the form Y. car because
these conditions are met, a weak update must be performed. Y may have no value or the value nil. This situation arises
Condition (1) is satisfied if the assignment is to a only if the program is errant or if the algorithm will later
variable or if the assignment is to a SSG node reached via a discover a path on which Y has a different value.’
deterministic variable. A strong update to a node n stops edges leaving n
Condition (2) is satisfied for SSG nodes that represent from propagating from an earlier SSG to a later SSG. Any
single heap nodes. A node in the SSG corresponds to a single right hand side of the form Y. car, where Y has no value or
heap node unless on some esecution path it has been merged has the value nil, is the site of a potential strong update.
with another SSG node. Rather than allow edges to be propagated past a statement
Careful treatment of merges allows detection of SSG that may later perform a stong update, we defer evaluation
nodes that represent single heap instances. All instances are until Y is given a value. This problem arises when the
flagged as either single instance nodes or multiple instance iteration has taken a path through the program in which
nodes. A single instance is guaranteed to correspond to an uninitialized variable is accessed; as shown in Figure 10,
at most one heap location. Multiple instance nodes may this can happen in a correct program. Such fragments can
correspond to any number of heap locations. commonly be found inside subroutines and loops. Most
An instance is generated at a cons statement, at which static analysis techniques (including this one) ignore the
point it corresponds to a single heap location. An instance values of predicates. They are unable to understand that
can become a multiple instance node only if it is merged the FirstTime flag assures that the assignment to Y .car is
under certain conditions. If instances ni and nr are merged safe.
to form instance na, na is a multiple instance node if any of A traversal of the program in Figure 10 might reason-
the following conditions hold: ably start by processing it as if FirstTime were false; first the
assignment to X, then the if test, and then the statements
l Instances ni and na are merged after an assignment following the if. On such a traversal, interpretation of the
statement (i.e., not at a join statement). assignment to X. car would add some edges to the SSG node
l At least one of rzr and nz is already marked as multiple of the first statement. This is followed by the assignment to
instance nodes. Y .car, but here processing must block because Y still has no
edges leaving it.
l Instailces nl and na were associated with the same Interpretation proceeds on some other path, and at
entering CFG edge at a join point. some later point the if-true branch will be processed, causing
Y to become defined. The statements following the if are
The second situation in which strong updates can be added to the worklist (again), but this time Y .car can be
applied arises when a variable V points to several SSG nodes correctly evaluated.
and there are no other edges into any of those SSG nodes.6 If the algorithm terminates without visiting a statement
The collection of SSG nodes models a run time situation s, then all executions of the program that include a path
in which one SSG node is referenced by V and the rest are through s will raise an error (or have undefined behavior.)’
unreachable (e.g., garbage for the collector). Whatever node We keep extra instances of SSG nodes that have vari-
V references will change, and the rest are not observable, so ables pointing to them because these instances correspond
it is safe to update all nodes referenced by V. to the heap cells that the program can manipulate easily.
Our propagation algorithm is organized around a work- By keeping these instances separate, strong updates can be
list. In order to deal with strong updates, the order in which performed on them and their references determined before
the statements are processed must be handled carefully. they are merged with the other nodes.
Two invariants are maintained: (1) when a statement is
visited, at least one of its immediate predecessors has already 4.3 Heap Reference Counting
been visited, and (2) an edge, once added to a statement’s
Additional information about storage structure can be ob-
SSG, is never deleted. Because an SSG contains a finite
tained by following the storage-shape analysis presented
number of edges, the second condition allows a trivial proof
here with a reference counting analysis similar to that of
of termination.
Hudak [Hud86] and Boehm and Hederman [BH88, Hed88]
(Barth uses a somewhat similar analysis for “compile-time
X + cons0 garbage collection” [Bar77].) The combined analysis can
discover that a list is a “true list”, and thus makes possi-
if FirstTime
ble optimizations like those described and implemented by
then do Larus [Lar89], without requiring programmer declarations.
Y+X Heap reference counting statically approximates the
FirstTime + false number of references to a heap cell from other heap cells;
end that is, it models a run-time count of heap references without
x.car + ... counting references from variables9 . The goal of heap refer-
Y.car + . . . ence counting is to discover portions of the storage shape
Figure 10. Program containing a legal use of an ‘An update to a deterministic variable may attempt to update
uninitialized variable. nil. In this case, the heap location cannot be modified and
the strong update would appear to be unjustified. However, any
To maintain the second invariant in the presence of attempt to update nil is necessarily an error and we do not worry
strong update, processing of some update statements must about getting correct results on errant programs.
‘Note that the algorithm will not detect all errors of this sort.
sBec,use of the meet rules, these conditions are satisfied only We think that the subset it does detect is probably uninteresting.
when each of the SSG nodes comes from a different cons statement ‘This is similar to the actual reference counting schemes de-
and each of the SSG nodes is a single instance node. scribed by Deutsch and Bobrow [DB76] and Rovner [RovSS].
301
graph that model lists or trees (as opposed to graphs with Statement
sharing or cycles); that is, the goal is to discover portions Graph and reference counts after execution
of the graph in which all nodes have heap reference count (1) X + nil
equal to one.
The rzfen:nce count lattice is (0, 1, oo} with meet oper- X -C nil
ation max. Each SSG node has an associated heap reference (2) while 0 do
count (HRC). Th e reference count of a node n is modified
whenever a field of an SSG node is updated to point to n. If
X -+ nil
the update adds a pointer to n, the HRC for n is incremented I / Y
(co + 1 + oo) We do not attempt to reduce heap reference
counts. Whenever two nodes are merged (at either a join
point or an assignment), the HRC for the joined node is the
maximum of the HRCs for the nodes that were joined. t t
HRC becomes a more powerful tool when combined with nil nil
the use of multiple instances, as shown in Figure 11. This (3) T + cons0
example builds a list in the usual way, by allocating new
SSG nodes and using the previous list as the cdr of the new X -c nil
list. With this storage shape graph, we can annotate each L
After statement (5) has been executed, no variables point to nil nil nil
the middle cons cell, and it is merged with the summary (5) X+-T
node. The maximum (meet) of one and one is one, so the
reference count of the summary is unchanged.
Notice th,zt the graph referenced by X. cdr (if not nil)
has reference count of one throughout. Any reachable nodes
are unshared i.f a subgraph of the storage shape graph has
the following properties:
1. The root of the subgraph is not reachable from the other (‘3) end
SSG nodes in the subgraph; Figure 11. List builder and reference counts.
2. all SSG nodes except the root have HRC = 1.
The intuition behind this is that if all nodes in a connected modeling this list, the count of references from next fields
graph have H:RC = 1, then the graph is either a tree or a will be one, and as long as paths traverse only edges rooted
simple cycle. If the root node is not part of a cycle, then what at next fields, different paths (rooted in a cycle-free node,
is reachable (i.e., has real reference count not equal to zero) as above) will address different nodes.
must be a tree. Given a storage shape graph annotated with The meet of two of these counts is m&x, and a count is
reference counts, a correctly rooted path that lies within a incremented whenever a reference from a corresponding field
region of HRC = 1 nodes is guaranteed to be a noncyclic at is created by an update. If counts are recorded only when
run time. Not,: that this is not the case for paths whose first they exceed zero”, then only a linear increase in space will
edge is from a variable directly into the non-rooted subgraph; result since there will always be at least as many edges as
these may be cyclic (but the presence of a reference from counts.
a variable does not invalidate the property for a correctly
rooted path). 5 An Efficient Implementation
This analysis is capable of discovering that a Yree”
“I’he simple conceptual version of our algorithm presented
built from the top down (as opposed to the bottom-up
in Section 3 may be too slow for practical use. Before
construction in the example here) is in fact a tree, and
we present our efficient algorithm, however, it is useful to
Can also discover that the destructive concatenation of two
analyse the simple algorithm.
proper lists is also a proper list.
if a program has S statements, then there can be as
Further &inements of reference counting can be used
many as S allocation statements and S summary nodes.
to extend these results. Each node can also maintain a
A variable can deterministically point to only one node, so
count for the n.umber of references from a specific field of any
node allocated. at a given statement; that is, an additional
count for each valid statement-field combination. With this “Actually, these counts need be maintained only when they
extension, it is possible to discover non-cyclic paths through exceed one, since no edges from fields-of-nodes-from-a-given-
cyclic structures. For example, a doubly linked list is cyclic, statement means zero, some edges means one, and more is a
but paths through the “nexIt” field are not cyclic. For nodes special case.
302
there can be 2 x V non-summary nodes in the SSG, where to the SSG node meet, the edge sets must be unioned
V is the number of variables. Thus, the number of nodes in together. In SSA form a &function would be inserted to join
each SSG is bounded by 5’ + V. We denote the maximum the differing assignments. Here, a new edge set is inserted
of the in-degree of a node and the maximum out-degree of to represent the union of the incoming edge sets. We call
fields within nodes and variables by T, and thus the number these new edge sets &functions, a.3 in SSA form.
of edges in each SSG is bounded by (S + 2 x V) x T. In the Just as in SSA form, it is desirable to insert the min-
worst case T = S+ V. Since there are S different SSGs, the imum number of &functions. Unfortunately, the efficient
storage required can be O(S x (S + V) x T). SSA calculation algorithm cannot be directly used here.
Each statement can be visited as many times as it has In computing SSA form, the side effects are visible before
edges in its SSG, O((S + V) x T). Every time a join node is the computation begins, and an assignment to a variable
visited, the SSGs from the two entering edges are merged”, modifies that variable only. Here, however, side effects are
so the work involved can be 0( (S + V) x T). There are d\S) discovered as the analysis proceeds; an assignment to a field
statements, and hence the total work can be O(Sx (S+V) x in one SSG node (e.g., x. car) may later be an assignment to
2”). While other work is done, this is the dominant cost. the same field of other nodes. Because of this, &functions
We improve the algorithm in two ways: will be inserted on the fly as side-effects are discovered.
Some aspects of the SSA algorithm are used. The
1. ‘We modify the data structures so that they take ad- dominance frontieris computed and used to determine where
vantage of any sparseness in the SSGs, as described in to locate the &functions. The dominance frontier DF(X)
Section 5.1. of a CFG node X is the set of all CFG nodes Y such that X
dominates a predecessor of Y but does not strictly dominate
2. We modify the algorithm so that changes to the SSG are Y. In SSA form, the defining assignment dominates all
propagated directly to where the information is used, as of the regular uses, and dominates all of the immediate
described in Section 5.2. predecessors of &function uses.
Each of these modifications allows us to replace a factor of The algorithm for computing SSA form connects. uses
S by a smaller term. Figures 12 through 17 contain pseudo- to definitions in a single pass over the program. We do not
code for the algorithm. want to make a pass over the program every time we discover
a new assignment, so a new data structure is required. After
5.1 Using Sparseness &functions have been inserted, the defining assignment for
a use can be located by searching up the dominator tree for
The SSGs are sparse in two ways: the nearest assignment. A new data structure is used to
1. Each SSG is likely to be sparse. Empirical studies of make this search efficient.
heap allocated structures have found that the reference Let T be a tree, which we call a master tree, with a
counts of over 90% of the cells never exceed one [CG77], set of nodes N. T’ is a skeleton tree for T if (1) the set
and systems relying on this assumption have worked of nodes N’ in T’ is a subset of N and (2) the parent of n
well [DB76, SCN84, Rov85]. Thus, one expects that in T’ is the closest ancestor of n in T that is in N’. We
an SSG should also be sparse. Given that the SSG is need to perform several operations on skeleton trees: insert
adequately sparse, we can assume that T is O(1). a new node, find parent, find all children. These operations
can all be performed in a straightforward mannerI’ in time
2. All SSGs have the same nodes and differ only in their O(] N’ I), or in time O(log(] N’ I)) time using the techniques
edges. Because each SSG is sparse, an update tends in [CWZSO].
to change only a small number of nodes. Hence, the In this algorithm, the master tree is the dominator tree
edge set of an SSG is very similar to that of the SSG’s of the control flow graph. For each node in the SSG, we
preceding statements. maintain a skeleton tree containing the use and definition
locations of the node. Each definition point in this tree
So far, the data structure used to represent the in- contains an SSG edge set. This tree is also used to find the
formation algorithm has one graph per statement. Each uses reachable from any definition. To determine the edges
graph has the same set of nodes, but the set of edges at a use, the nearest definition point is located by walking
leaving corresponding nodes differs. Here we invert that up the skeleton tree from the use point until the edge set is
representation using only one set of nodes. Each node has found.
a list of its different edge sets. Associated with each edge Each SSG has the same set of nodes. To take advantage
set is the location (the statement) at which that set is valid. of sparseness, we require that the value of a node in the SSG
A node has an edge set at a location 1 if the edge set for for statement S can usually be derived from the value of
that node differs from any of the edge sets of the immediate the corresponding node in the ,SSG<(o) for the CFG prede-
predecessors of I in the control flow graph. cessor(s) of S. The corresponding node can be easily found
The question is: which statements need edge sets at in the simple algorithm because each SSG node corresponds
which SSG nodes? In straight-line code, this is easy to to a single cons statement.
answer: the only statements that need edge sets are the We allocate for the whole program a fixed set of SSG
updates to that SSG node. Real programs contain branches nodes, one SSG node for each cons site to hold the summary,
and joins, however, and to handle them, we use an idea one SSG node for each variable, and one SSG node for
borrowed from SSA form. In translating to SSA form, a each variable to point to deterministically, which we call
d-function for variable V is inserted at any join point that
different assignments to V reach. Here, we treat each SSG
node as if it were an SSA variable. An update to an SSG 12Find parent and find all children are trivial. Insert can be
node can be thought of as an assignment to an SSA variable. done as foLlows: by using a preorder numbering of the master tree
At the control flow graph join points, where differentupdates and a count of the number of descendants of a node in the master
tree, one can in unit time tell whether one node is a descendant
of the other. To insert a node in the skeleton tree, walk down
l1 We assume for simplicity that no more than two edges come from the root of the skeletal tree until you find a node that is the
into a join node. parent of the node you are inserting.
that variable’s cons cell. Each allocation site has a single 5.2 The Propagation Algorithm
summary node. The summary nodes and the SSG nodes In the simple algorithm, whenever the evaluation of an
correspon&ng ‘:o variables match up in a one-to-one manner assignment changes the edge set for the target, the control
between slaternents. In the variable’s cons cell, the cor- flow graph successors of the basic block are added to the
respondence is not straightforward. Consider the following worklist for future reevaluation. In the efficient algorithm,
code sequence: on the other hand, only the statements using the values com-
puted at the assignment are queued for reevaluation. Thus
1 x + COll.Sl the reevaluation need not be done on statements between
2 Y+X the definition site and the uses.
3 X 4- cons3 Strong update causes a problem: a basic block con-
taining an apparently erroneous update is treated as not
In statement (l), X’ s cons cell holds the value of consl. executable, and attributes do not propagate through it. A
In statement (:I) X and Y must point to the same cell, and technique borrowed from constant propagation [WZ88] is
we choose (somewhat arbitrarily) to use X’s cons cell, since used to mimic the careful evaluation required by strong up-
the value is already there. In statement (3) X’s cons cell dates. The incremental algorithm has two global worklibts,
must be used f’or the value of cons3. The value produced and elements are chosen from whichever one has elements of
by cons1 is now stored in Y’s cons cell. To move the cell work that need to be done. The first worklist contains basic
from X’s cons 1;o Y’s cons requires copying the values from blocks; the second worklist contains uses whose values may
cons to Y’s cons, finding all pointers to X’s cons cell, moving have changed since they were last visited.
those pointers to Y’s cell, and initializing all of the fields in We track whether a basic block has ever been visited
X’s cons cell. and whether it has been successfully executed to completion.
When a basic block is pulled off the worklist it is marked as
Thus, certain operations on one SSG node may bring
“visited” and is traversed statement by statement, locating
about a causing a certain amount of shuffling in the SSG
uses and definitions within the basic block and queueing uses
nodes that are deterministically pointed to. The variables
onto the second worklist. In certain situations (specifically,
and SSG nodes that point to shuffled SSG nodes must
field selection through an uninitialized variable), processing
actually be updated to reflect the change. These updates are
cannot proceed and the basic block must be marked as
treated like all other updates to variables’ SSG nodes and
“visited” but not completed. If processing reaches the end
their impact must be propagated throughout the program.
of a basic block, the basic block is flagged as successfully
This shuffling effect can happen not only at assignments but
executed to completion. When a basic block is successfully
also when instances are merged.
completed, its CFG successors are placed in the first work-
To perforrn the shuffle operation, we need to find all list.
nodes pointing at a given node. To find them efficiently, a When a definition is discovered, &functions must be
list can be maintained for each node of every reference to inserted at the blocks in its dominance frontier. This
that node. Every time a reference is added to that node, insertion is deferred until an error-free path is found from
this list needs KO be updated. The list can be treated as an the definition site to the block in the frontier. The deferred
extra field of a node, and maintained on a skeleton tree. At insertion is accomplished by queueing &functions in a per-
a skeleton tree node for this field, a new copy of the list is block worklist at the predecessor(s) of the block in the
maintained with whatever changes are appropriate. frontier. If the predecessor executes to completion, then a
When an assignment to a variable takes place, and path has been found and the deferred #-functions can be
that variable no longer deterministically points to its former inserted.
cons cell, that cell must either be shuffled to a different When an item is pulled off the second global worklist
variables cons cell or merged with the summary node. A it is tested to see if it is the same as before; if not, the
pass is made over the list to see if any variables point effect of its new value is propagated. Any updates done as
to it deterministically, and the first one found is choosen. part of this statement cause additional items to be placed
All changes tc various fields caused by the shuffling are on the second worklist. If a previously uninitialized variable
propagated in .the normal manner. appearing in a selection becomes defined, then a previously
At a join point, a variable may become non- stuck statement may become executable and the basic block
deterministic. This forces a shuffle if a node was stored in may be executed to completion and its successors added to
that variable’s cons cell. A shuffle in the statements leading the first worklist.
to a join point may also trigger a shuffle at the join point. When merging SSG nodes n1 and na, not only are nl
But it is also possible at a join point to have the node stored and ns treated as being updated, but so are the nodes that
in different variable’s cons cells on different entering CFG point into nl and n2.
edges. In that case, one of the cons cells is chosen at the One important property of this analysis is that the
join point (if one had been chosen from one of the entering number of basic blocks flagged as visited and successfully
CFG edge’s, and the other CFG edge changes, we stay with executed increases monotonically as the algorithm proceeds;
the old choice). For this SSG a forwarding pointer is kept thus, the efficient/incremental algorithm may be freely used
from the node not chosen to the one which is chosen. When without regard for order of execution. This is insured
a change is propagated to the node not choosen, rather than (partially) by placing on the second worklist only those uses
update that node, the algorithm must recognize that there that can be reached by some simulated path through the
is a forwarding pointer and update the node pointed to by CFG. A more subtle property is also required to insure
the forwarding pointer. If a shuffle is performed at the join convergence of the efficient algorithm: weak updates without
point, moving a node, all forwarding pointers to the node intervening uses may be performed in any order because a
must also move. weak update can only add edges, and conversion of a strong
Heuristics may improve shuffling behavior. Some pos- update into a weak update cannot delete any edges from any
sibilities incluc!e an arbitrary ordering of the variables to SSG.
determine which is chosen at a shuffle, and a preference for The algorithm presented here consists of a driver, a
shufl’ling to variables not involved in pseudo-assignments. subroutine to process basic blocks from the worklist, a
304
do DoBlock (B)
WORK + {ROOT} S + nextstmt(B)
visited + {ROOT} stuck + false
thru + {} while S not equal last(B) and not stuck do
case rhs(S) in
while WORK not empty do ‘I’ : AddUse(x, S, RHS, S)
take item from WORK ‘x-a’ : AddUse(x, S, RHSSEL, S>
case item in forall y in addx(x.a.S)
BLOCK : DoBlock(item) AddUse(y, S, RHS, S)
USE : Douse (item)
I4’ : ignore it
endcase endcase
end case lhs(S) in
end ‘I’ : AddDef (x, S, eval(rhs(S) ,S>>
‘x.a’ : AddUse(x, S, LHSSEL. S)
Figure 12. Driver. if no edges leaving x
then stuck + true
Douse (use> else
(oldval, definer, stmt, type, key) + use forall y in addr(lhs(S) ,S)
delta + evalcdef iner, stmt) - oldval AddDef(y, S, eval(rhs(S),S))
if delta not empty then endif
case type in endcase
LHSSEL : if not stuck then S +- successor(S) endif
forall n in delta do end
forall f in if stuck
addx(n.sel(lhs(stmt)) ,stmt) do then nextstmt(B) + S
AddDef (f , stmt , else
eval (rhs (stmt > , key) > thxu + thru + B
end forall (N,C) in queue(B) do
end AddPhi(N, B, C)
if previously there were no fields end
in the l-value of stmt and nov forall C in succ(B) - visited do
there is at least one, add B to WORK
then add B to visited
add stmt’s block to WORK. end
endif endif
RHSSEL : end DoBlock
f oral1 n in delta do
forall f in Figure 14. Blocks.
addx(n.sel(rhs(stmt~),stmt) do
AddUse(f, stmt , RHS, stmt)
end The algorithm uses the following terms:
end
RHS, PHI : df (x) Dominance frontier of x (a set of block-to-block
forall f in ad&(lhs(stmt) , stmt) do edges).
f oral1 u in defs(f 1 (atrat> .uses do
add u to YORK defs(x) Definitions for x. Def s(x) (p) is the definition for x
end reaching point p. A definition is a triple (stmt , value,
uses) +
end
endcase
WORK A list of uses and blocks. Basic blocks on the list
endif are eligible for execution; uses on the list have changed
end Douse definitions. Execution of a basic block B begins at
nextstmt (B). For simplicity, each basic block has empty
Figure 13. Uses. statements first(B) and last(B) where &functions
may be attached.
subroutine to process uses of changed definitions, and sub- use A “use” is a quadruple (value, stmt , type, key),
routines to insert new uses, new definitions, and new d- where value is the most recently computed “value”
functions. The insertion subroutines also schedule items (nodes addressed) seen at this use, stmt is the statement
onto the worklist as necessary; a new use propagates a at which the use occurs, type is the type of use, and key
value forward, and new definitions can affect the values is the statement with which the use is associated (and
seen at existing uses. AddPhi and AddDef are mutually differs from stmt only for uses in &functions).
recursive; a new definition must propagate to $-functions
at its dominance frontier, but $-functions are definitions. ROOT The first basic block in the program.
305
AddUse(fit!ld, stmt, type, key) AddDefcfield, stmt, value)
(dstmt, dvalue, duses) - (dstm, dval, duses) +- defscfield, stmt)
defs(field, stmt) uses + (u in duses I stmt dominates u}
defs(fic!ld, dstmt) + defstfield, dstm) 6
(dstmt, dvalue, duses + (stmt, type, key)) (dstm, dval. duses-uses)
create 2~use u = defscfield, stmt> + (stmt, value, uses)
(evall:f ield, key), stmt, type, key) forall u in uses do
add u to YORK. add u to YORK.
end AddUsc! end
forall edges (bl,b2) in dfcstmt) do
Figure 15. AddUse. if def of field at stmt reaches last(b1)
then AddPhi(field, bl, b2)
AddPhi(fic!ld, defb, web) endif
if defb not in thru then end
add (field, web) to queuecdefb) end AddDef
else if 4 for field in useb then
AddUse(field, firstcuseb), Figure 17. AddDef.
PHI, last(defb))
else
neanodes + {}
forall B in pred(useb) intersect thru do no more than O(T) nodes. An assignment to a variable can
Add&e (f ield, first (useb) , PHI, last (B) ) cause a merge of two nodes, which causes an update of all
nev:nodes c eval(f ield, last(B)) O(T + 1) nodes pointing to it. Each actual update may
end cause &functions to be added to the skeleton tree. These
AddDcE(field, useb, nevnodes) are at the dominance frontier of the update and recursively
endif to the dominance frontiers of those &functions. This is
end AddPhi exactly like adding an assignment to a program in SSA form
and seeing how many more pseudo-assignments are added.
Results in [CFR+ 89a, CFR+ 89b] show that in practice the
Figure 16. AddPhi. number of pseudo-assignments per assignment tends to be
a small constant. However, since in the worst. case it could
be O(S), we call the average number of potential updates
visited The basic blocks that have been placed on the added P. The number of SSG nodes in all of the skeleton
queue at least once. trees will be O(S x T x P).
thru The basic blocks that have been executed to comple- Since the number of edges is proportional to the overall
tion. running time of the algorithm and inversely proportional to
the quality of the information gathered, it may be perfectly
lhs(s) Lhs expression of s.
reasonable to abort the algorithm if the total number of
rhs(s) Rhs expression of s. edges approaches becoming quadratic, since the information
would be quite poor. This can help ensure that T remains
pfx(e> Prefix Iof a selection expression. small.
gel(e) Selector of a selection expression. A useful abuse of The cost of adding an update or potential update has
notation aill be “addr(x.sel(lhs(stmt)))“, meaning two parts: updating the immediate node and propagating
“use the field selector occurring in the left-hand side of the effects to all new uses of the node. The most expensive
stmt to pick a field of the SSG node x”. part of updating a node is the potential insertion in the
skeleton tree. With the sophisticated insertion algorithm,
addr (e , S> Fie’lds/variables addressed by an expression. this takes O(log(S)), and thus the cost of update only for a
node is O(S log(S) x T x P). Updating a variable can cause
deref (f , S) Nodes reached by traversing arrows leaving the a merge and updates of nodes pointing at the merged node.
field or variable f. The cost of updating the nodes pointing to the merged node
eval(e,S) {deref(f,S)lf E addr(e,S)}. is O(S log(S) XT x P); the cost of the merge itself depends on
the number of fields Fin the node and is O(Slog(S) x FxP).
Note that the parameter S is necessary to indicate the
statement at which the expression, field, or variable The uses of a new edge can be found in time O(T x
is being evaluated. As an abuse of typing, singleton the number of uses of that node). For each use, if a variable
sets and single elements are used interchangeably where node has just been updated, O(T) steps are done on the LHS
convenient. and O(max(Tlog(S),T*)) on the right hand side to recom-
pute the new set of nodes pointed to. If a heap node has just
been updated, O(max(log(s), T)) steps are required. A node
5.3 :I$. Bounds for the Efficient Algo- can be updated at most O(T) times. The O(S uses of vari-
ables in the program contribute O(max(S x 4 ), ‘s lO.dS) x
The size of the inverted data structure is dependent on the T*)) work. There are potentially O(S x T) uses of nodes,
product of the number of nodes in the SSG (O(S f V)) and they contribute O(max(S x p),Slog(S) x 57’)) work
and the size of the structures under them. Each assignment as well. Thus the time bound is O(max((Slog(S) x T x
statement to a heap element (e.g. X.car + . . . ) can update P),(Slog(S) x F x P),(S xp),Slog(S) xT2)).
306
6 Interprocedural Analysis use variables to separate the nodes. However, there will still
be only one summary node for all the nodes allocated in the
Our method for interprocedural analysis is straightforward: called procedure.
we model procedure calls with a branch to get to the Procedures may be integrated into the program. This
procedure, a labeled branch to return and assignments to is particularly sensible where they are small and where they
model parameter passing. In this section we examine the allocate only a few cons cells. The entities our technique
details and the consequences of analyzing a program as a analyzes are the individual cons sites. Consider a leaf
single procedure. procedure called from many places whose main purpose
A call becomes an assignment to a label, some assign- is to allocate (and possibly initialize) a piece of storage
ments to model parameter passing and an assignment to that is returned. We lose information if we don’t integrate
a label variable of the location immediately following the the procedure. In the worst case, if the cons procedure
call. A return is simply a case statement using the label itself is not integrated, then all distinction between different
and a jump. Thus, in each branch of the case statement allocation sites will be lost.
in the flow graph, the case statement has edges leading to Interprocedural analysis algorithms have tended to use
all locations following calls to the procedure, and we lose the following framework [Bar78, Ban79, Mye81, Bur87,
the information that a return is associated with a call. We Ca188, CK89]:
have a different labeled variable for each procedure, and our
graph reflects the fact that the return from procedure “f oo” 1. A summary is built of each procedure that describes
cannot return to the statement following a call to a different the effects of calling that procedure on the parameters
procedure “bar”. (This is why we use a case statement and global variables. These summaries are generally
rather than a labeled jump.) Modeling value or value returns pow-insensitive, i.e., they discard all of the information
via assignments is straightforward. The assignments for the about paths within the procedure.
return can be put in the case statement.
At first one might think reference parameters should 2. A call graph is constructed. A call graph is a directed
be modeled with pointers: any variable that is passed by multigraph in which the nodes represent the procedures
reference becomes a pointer to a node holding the actual and there is an edge from procedure X to procedure Y
value that the programmer associates with the variable. for each call from X to Y.
Unfortunately, this interferes with our heuristics for keeping
multiple copies of a node (see Section 4.1), so we suggest 3. A data flow analysis problem is solved over the call
a different technique based on the observation (in [WZSS]) graph using the summary information as the initial
that, at least for the purposes of analysis, call by reference conditions.
can be modeled by call by value-result and some extra
assignments. There are three cases: 4. The interprocedural information computed in the pre-
vious step is used to optimize each procedure.
1. If the call by reference parameter is never aliased with
any other variable, then it can be replaced by a call by This framework has been justified through two assump
value-return parameter. tions: (1) little information is lost during by summarizing,
and (2) even if the loss is substantial, you could not afford to
2. If the call by reference parameter is always aliased with do otherwise. While historically correct, we feel that these
a set of variables, then it can be replaced by a call assumptions need to be reassessed.
by value-return parameter. Any assignment to one of
those variables is replaced by assignments to all of them; Our analysis associates the information with the indi-
wherever possible, these assignments may be done using vidual cons sites on the assumption that memory from
strong updates. different cons sites is used in different ways. Flow-
insensitive summaries destroy such knowledge.
3. If the call by reference parameter may sometimes be
aliased with a set of variables, then for the purposes of Most modern machines have substantial amounts of real
analysis it can ‘be replaced by a call by value-return memory and extremely large virtual address spaces. On
parameter. An assignment to one variable can be such machines, performing summarization to save space
replaced by a may assignment to the other variables. is unnecessary.
For our analysis here, an assignment to one variable can
be modeled as a weak update to all the other variables. Algorithms based on propagating bit-vectors have
At runtime, this must still be implemented as call by quadratic time bounds at best (the width of the bit
reference. vector times the number of nodes in the call graph).
With nonlinear algorithms, care must be taken to limit
The analysis to determine which parameters can be aliased growth in the significant parameters. We expect our
can be performed by techniques given in [Bar78, Ban79, algorithm to be much more efficient than previous
Bur87, CK88, Mye81, WZ88]: algorithms; thus the number of nodes can grow in
A major drawback of this analysis is that a procedure, a reasonable way without the performance becoming
which may be called from several places, may allocate cons unreasonable.
nodes. Those nodes all come from the same static allocation
statement and hence we have a single summary node for all In order to take advantage of the expected sparseness
of them. We can hope that the calling procedures all use the in the information, our algorithm uses explicit lists
nodes in the same way and update them in similar ways, so of edges rather than bit-vectors. The speed of our
that the analysis of one program section does not create an algorithm (and the quality of the information gathered)
SSG more general than is needed by a different section. is inversely proportional to total size of these lists: the
If a procedure allocates nodes and keeps those nodes smaller the list, the faster the algorithm runs (and the
pointed to by variables, the heuristics in Section 4.1 may better the information discovered). This has the follow-
keep those nodes separated from the summary node for that ing counterintuitive property: an algorithm using the
allocation site. This requires that the calling program also non-summarized version (which may be considerably
larger than a summarized version) may actually perform Choosing to summarize together all nodes deeper than
better because the higher-quality fixed point is closer to k in a data structure ignores any hints provided by
the initial conditions. program structure. When summarizing, it is useful to
combine nodes with similar attributes so that as little
While we generally expect our algorithm to be linear, information as possible is lost in their meet. Two nodes
one case raises some concern: if one kind of data structure allocated at the same statement are more likely (we
that has been allocated at many points in the program is believe) to be similar than two nodes occurring deep
manipulated by a single function, that function may be within a data structure, and the analysis should take
expensive to analyze. This is because the variables within advantage of this.
that function may point to a large number of nodes, each of
which has beer. allocated at a different allocate statement. k-bounded truncation makes it difficult to maintain
information about the elements of a list. Truncation
7 Comparison With Other Work is typically done at the deepest node in the structure:
Extant techniques view the program as a generator of data all nodes deeper than k are merged into their immediate
structures. Each cons statement in the program adds nodes ancestor. When this ancestor is a node in the spine of
to the data structure. When the size of the data structure ex- the list, the structure and abasing of the elements of
ceeds some bound, these nodes are combined into summary the list are summarized with the structure and aliasing
nodes. The limit on graph size is often based on a bound, of the list spine. The result provides little information
k, on the maximum acyclic path length [Sch75a, Sch75b, about list or element structure.
JM81, Rug87, RM88, LH88, Lar89, HPR89], hence these For example, consider truncation of the graph shown
are called k-bounded techniques. If the data structures being in Figure 20, where the deepest cons node is
analyzed are recursive, the size of the data structure will be X.cdr.cclr.car. A naive truncation of that tree, shown
unbounded. Therefore, graphs for programs with recursive in Figure 21, summarizes the node with its parent, in-
data structures; must contain summarized components. troducing a cycle to describe a structure that is not only
As an example, consider the first loop in the program in acyclic but also of small bounded size. Any differences
Figure 2 with the path length bounded to three cons nodes. in the attributes of the list spine and the list elements
At the end of the second iteration of the loop, a summary is are also lost. Figure 22 shows the final summary after
required. The i;raph before summary is shown in Figure 18. continued growth of the list.
Summarization must discover a shorter representation for
-2
2w
X
1
nil
2
-+2
w Figure 21. A bad summary.
1
X nil
s- ELF
this list that still contains all paths in this list. Figure 19
shows two possible truncations of this list. Existing trunca-
tion processes shorten the list as little as possible, and hence Figure 22. Summary after additional growth.
end up with the right-hand alternative. However, the left-
hand alternative (which is what we obtain) contains more
useful information because it retains the periodic structure The process of truncation is fairly complex (and differs
of the list. greatly among those papers that use the technique).
The k-bounded techniques have several disadvantages:
The method described in this paper has none of these .~
l Choosing to limit path length or node label size to k drawbacks. Nodes combined in the same summary are alIo-
makes possible a blowup exponential in k; a complete cated at the same site (thus exploiting program structure);
binary tree of depth k contains 2k - 1 nodes. In practice the elements of a list are (typically) summarized separately
k is chosen very small (2 or 3) so blowup is not a from the spine of the list; the truncation process is simple.
problem, but this choice greatly reduces the amount of Jones and Muchnick [JM82] were the first to describe
information that can be retained. a method for analysis of unbounded data structures based
308
on summarizing multiple nodes in a data structure into a iteration of the loop. Doing so requires a single-instance
single node based on a fixed node set. However, their model node. We need a mechanism for unmerging a summary node
does not include updates. In one example, they, like us, into a summary and a single-instance node.
choose summary nodes based on points in the program. While we can fit multiple summaries and unmerging
They attempt to get information that is more precise than into our framework, we must develop the mechanisms that
ours, but at a substantial time cost. trigger their use in a wide variety of programs. We have
Work by Chase [Cha87] uses similar techniques for developed mechanisms which work on isolated examples, but
choosing nodes for summaries, but does not provide an a good general mechanism has so far eluded us.
efficient algorithm (O(n’) for programs with side effects,
where n is the number of statements in the program), Telling the programmer: The information that we au-
and does not address strong updates or the association of tomatically collect may help programmers understand what
additional attributes with graph nodes. Ruggieri [Rug871 their program does. Currently data structure editors help
provides a complexity result of O(lVl” x ISI x n), where give an idea of what a dynamically produced data structure
S is the number of allocation sites, n is the number of looks like. It is possible that an editor could be built on
statements in a program, and V is the number of variables top of the technology discussed in this paper to look at all
and “subvariables” (but in the worst case IV1 is exponential possible data structures buildable by a program.
in a parameter k).
k-bounded methods described by Larus [LH88, Lar89] 9 Conclusion
can obtain strong updates in some situations. His conditions
The analysis presented above obtains useful information
for strong update are similar to ours; he does not discuss the
about linked data structures. We summarize unbounded
constraints placed by strong update on the order in which
data structures by taking advantage of structure present
statements are processed. Other work appears not to discuss
in the original program. The worst-case time bounds for
strong updates.
a naive algorithm are high-degree polynomial, but for the
For languages with side effects, only Hendren’s tech-
expected (sparse) case we have an efficient algorithm. Pre-
nique [HN89] automatically discovers that recursive data
vious work has addressed time bounds rarely, and efficient
structures are unshared (i.e., lists and trees). This informa-
algorithms not at all.
tion is very important; given declarations identifying true
The quality of information obtained by this analysis
lists and trees, Larus has performed additional analysis and
appears to be (generally) better than what is obtained by
useful optimizations on Lisp functions manipulating linked
existing techniques. A simple extension obtains abasing
data structures [Lar89]. Hendren’s work discovers trees and
information for entire data structures that previously could
DAGs for use in dependence analysis. It is not clear whether
be obtained only through declarations. Previous work by
her work can be easily extended to provide lifetime analysis
Larus has shown that this information allows worthwhile
or to allow value approximation within heap cells, or if it
optimization.
can obtain the information provided by extended models of
We believe that practical analyses based on this work
references counting.
Deutsch [DeuSO] describes a similar analysis for strict can be used in compilers for languages that provide linked
data structures.
higher-order functional languages with lexical scoping, poly-
morphism, and first-class continuations. He does not treat
side-effects (there are none) and doesn’t address efficiency of References
analysis. [Ban791 J. B. Banning. An efficient way to find the
Stransky also proposes a similar analysis in his the- side effects of procedure calls and the aliases
sis [Str88], but we are unable to compare our work with of variables. Conf. Rec. Sixth ACM Symp. on
his because our French is not adequate. His work appears Principles of Programming Languages, pages
not to address strong updates, tree detection, or efficient 29-41, January 1979.
algorithms.
[Bar771 J. M. Barth. Shifting garbage collection over-
8 Future Work head to compile time. Comm. ACM, 20(7):513-
518, July 1977.
While there are many aspects of the analysis problem that [Bar781 J. M. Barth. A practical interprocedural
we have addressed, we realize that there are still many data flow analysis algorithm. Comm. ACM,
unresolved issues: 21(9):724-736, September 1978.
Implementation: We have made some assumptions [BH88] H.-J. Boehm and L. Hederman. Storage allo-
about the sparseness of certain structures. Based on these cation optimization in a compiler for Russell.
assumptions, we have developed techniques and data struc- Submitted for publication, July 1988.
tures that we feel may perform well in practice. Mea- [Bur87] M. Burke. An interval-based approach to ex-
surements of real programs are necessary to prove these haustive and incremental data flow analysis.
assumptions. Technical Report 12702, IBM, Yorktown Hts.,
Enhancements to the information: Programs often New York, September 1987.
take a pre-existing data structure and modify it. For ex- [CalSS] D. Callahan. The program summary graph and
ample, we do not get very good information when analyzing flow-sensitive interprocedural data flow analy-
a program that reverses a list in place. There are at least sis. Proc. SIGPLAN’88 Symp. on Compiler
two problems. (1) We h ave restricted ourselves to using Construction, 23(7):47-56, July 1988.
only one summary node. As the list is reversed, we need [CFR+89a] R. Cytron, J. Ferrante, B.K. Rosen, M.N. Weg-
to have one summary node for the elements that we have man, and F. K. Zadeck. An efficient method of
finished processing and one for those we have yet to start computing static single assignment form. Conf.
processing. These two nodes cannot be merged and retain Rec. Sixteenth ACM Symp. on Principles of
the information we want. (2) We need to make strong Programming Languages, pages 25-35, January
updates to the node whose fields we are reversing in this 1989.
309
[CFRt89b] R. Cytron, J. Ferrante, B.K. Rosen, M.N. Weg- [LH88] J. R. Larus and P. N. Hilfinger. Detecting
man, and F. K. Zadeck. Efficiently computing conflicts between structure accesses. Proc.
static single assignment form and the control SIGPLA N’88 Symp. on Compiler Construction,
dependence graph. Technical Report RC 14756, pages 21-34, July 1988. Published as SIGPLAN
IBM, July 1989. Notices Vol. 23, Num. 7.
[CG77] D. W. Clark and C. C. Green. An empirical [My4 E. W. Myers. A precise interprocedural data
study of list structure in LISP. Comm. ACM, flow algorithm. Conf. Rec. Eighth ACM Symp.
20(:2):78-87, February 1977. on Principles of Programming Languages, pages
[Cha87] D. R. Chase. Garbage Collection and Other 219-230, January 1981.
O~timitotions. PhD thesis, Dept. of Computer [RM88] C. Ruggieri and T. P. Murtagh. Lifetime analy-
Sci., Rice U., August 1987. sis of dynamically allocated objects. Conf. Rec.
[CK88] K. D. Cooper and K. Kennedy. Interproce- Fifteenth ACM Symp. on Principles of Pro-
du:ral side-effect analysis in linear time. Proc. gramming Languages, pages 285-293, January
SIGPLA N’88 Symp. on Compiler Construction, 1988.
pages 57-66, June 1988. Published as SIG- [Rov85] P. Rovner. On adding garbage collection and
PLAN Notices Vol. 23, Num. 7. runtime types to a strongly-typed, statically
checked, concurrent language. Technical Report
[CK89] K. D. Cooper and K. W. Kennedy. Fast inter-
CSL-84-7, Xerox Palo Alto Research Center,
procedural alias analysis. Conf. Rec. Sizteenth
Palo Alto, Ca. 94304, 1985.
ACM Symp. on Principles of Programming Lan-
guages, pages 49-59, January 1989. Austin, PWW C. Ruggieri. Dynamic Memory Allocation Tech-
Te:uas. niques Based on the Lifetimes of Objects. PhD
thesis, Purdue University, August 1987.
[CWZSO] D. R. Chase, W. Wegman, and F. K. Zadeck.
Fast insertion, deletion, and lookup in sparse [Sch75a] J. T. Schwartz. Optimization of very high level
ansestor trees. Technical Report CS-90-07, languages-I: Value transmission and its corol-
Dept. of Computer Sci., Brown U., March 1990. laries. Computer Languages, 1:161-194, 1975.
[DB76] L. Peter Deutsch and Daniel G. Bobrow. An [Sch75b] J. T. Schwartz. Optimization of very high level
efficient, incremental, automatic garbage collec- languages-II: Deducing relationships of inclu-
to1. Comm. ACM, 19(9):522-526, September sion and membership. Computer Languages,
1976. 1:197-218, 1975.
[SCN84] W. R. Stoye, T. J. W. Clarke, and A. C.
[DeuSO] A. Deutsch. On determining lifetime and alias-
Norman. Some practical methods for rapid
in@, of dynamically allocated data in higher-
combinator reduction. SIGPLAN Symposium
order functional specifications. Conf. Rec. Seu-
on LISP and Functional Programming, pages
en teenth ACM Symp. on Principles of Program-
159-166, 1984.
ming Languages, pages 157-168, January 1990.
[Str88] J. Stransky. Analyse skmantique de structures
[Wed881 L. Hederman. Compile time garbage collection.
de donne’es dynomiques auec application au cas
Master’s thesis, Dept. of Computer Sci., Rice
particulier de langages LISPiens. PhD thesis,
U., 1988. UniversitC de Paris-Sud, Centre d’orsay, June
[HN89] L. J. Hendren and A. Nicolau. Parallelizing 1988.
programs with recursive data structures. Proc. B. Wegbreit. Property extraction in well-
1989 International Conf. on Parallel Process- Weg751
founded property sets. IEEE Trans. on Soft-
ing, 11:49-56, 1989. ware Engineering, SE-1(3):270-285, September
[HPRSS] S. Horwitz, P. Pfeiffer, and T. Reps. De- 1975.
pe:ndence analysis for pointer variables. Proc. [WZ88] M. N. Wegman and F. K. Zadeck. Constant
SIGPLAN’89 Symp. on Compiler Construction, propagation with conditional branches. Techni-
June 1989. Published as SIGPLAN Notices Vol. cal Report CS-88-02, Dept. of Computer Sci.,
24. Num. 7. Brown U., February 1988.
[Hud86] P. Hudak. A semantic model of reference count-
ing and its abstraction. In SIGPLAN Sym-
posium on LISP and Functional Programming,
pages 351-363, 1986.
[JM81] N. D. Jones and S. S. Muchnick. Flow analysis
and optimization of LISP-like structures. In
S. S. Muchnick and N. D. Jones, editors, Pro-
grtrm Flow Analysis, chapter 4, pages 102-131.
Prentice-Hall, 1981.
[JM82] N. D. Jones and S. S. Muchnick. A flexible
approach to interprocedural data flow analysis
and programs with recursive data structures.
Conf. Rec. Ninth ACM Symp. on Principles of
Programming Languages, January 1982.
[Lar89] J. R. Larus. Restructuring symbolic programs
for, concurrent execution on multiprocessors.
Technical Report UCB/CSD 89/502, Computer
Sci. Dept., U. of California at Berkeley, Berke-
ley; CA, May 1989.
310