22.08.2013 Views

Parallelizing the Construction of Static Single Assignment Form

Parallelizing the Construction of Static Single Assignment Form

Parallelizing the Construction of Static Single Assignment Form

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Algorithm 2 Amendment for lazy φ-function insertion<br />

19: doall B : basic blocks in control flow graph<br />

20: for all v : variable names in original program do<br />

21: if <strong>the</strong>re is a queued φ-function for v at block B <strong>the</strong>n<br />

22: insert φ-function at block B<br />

23: end if<br />

24: end for<br />

25: end doall<br />

2.2.1 Commentary on Sequential Algorithm<br />

Once <strong>the</strong> φ-function insertion is complete, <strong>the</strong> second phase<br />

is to rename all definitions and uses <strong>of</strong> local variables to<br />

enforce <strong>the</strong> SSA property <strong>of</strong> having a single definition per<br />

variable in <strong>the</strong> program text, while respecting <strong>the</strong> original<br />

program’s data flow behaviour.<br />

The presentation <strong>of</strong> <strong>the</strong> classical renaming algorithm by<br />

Cytron et al [7] is phrased in terms <strong>of</strong> original variable names<br />

and new variable names. At each control flow point in <strong>the</strong><br />

program, we must maintain a mapping between original variable<br />

names and new variable names. This mapping changes<br />

as variable definitions enter and exit scope.<br />

The mapping is generated using an array <strong>of</strong> stacks S, indexed<br />

by original variable name. An individual stack data<br />

structure S(V ) contains new names corresponding to original<br />

variable name V . A new variable name Vi is pushed<br />

onto stack S(V ) at <strong>the</strong> ith definition <strong>of</strong> V encountered in<br />

<strong>the</strong> original program text. At <strong>the</strong> same time, <strong>the</strong> new name<br />

Vi replaces <strong>the</strong> old name V for that particular variable definition<br />

statement. Vi is popped <strong>of</strong>f <strong>the</strong> stack when its corresponding<br />

definition goes out <strong>of</strong> scope.<br />

At each statement that uses V in <strong>the</strong> original program,<br />

<strong>the</strong> new variable name Vi on top <strong>of</strong> S(V ) is substituted into<br />

<strong>the</strong> statement in place <strong>of</strong> <strong>the</strong> original name V .<br />

The CFG is processed according to a pre-order traversal<br />

<strong>of</strong> its dominator tree. The set <strong>of</strong> basic blocks Children(X)<br />

denotes <strong>the</strong> basic blocks whose immediate dominator is X,<br />

i.e. <strong>the</strong>ir parent in <strong>the</strong> dominator tree is X.<br />

The most complex part <strong>of</strong> <strong>the</strong> renaming algorithm involves<br />

φ-function right-hand side operands. The jth operand on<br />

<strong>the</strong> right-hand side <strong>of</strong> a φ-function for original variable V<br />

must be renamed according to <strong>the</strong> new variable name Vi that<br />

is in scope at <strong>the</strong> end <strong>of</strong> <strong>the</strong> jth predecessor basic block. Operationally,<br />

a φ-function for V at <strong>the</strong> beginning <strong>of</strong> block B<br />

is equivalent to n simple assignments to V at <strong>the</strong> end <strong>of</strong> <strong>the</strong><br />

n predecessor basic blocks <strong>of</strong> B. Thus it is most straightforward<br />

to rename φ-function right-hand operands during <strong>the</strong><br />

renaming <strong>of</strong> corresponding predecessor basic blocks. At each<br />

basic block, we must look ahead to check for φ-functions in<br />

successor basic blocks. The set <strong>of</strong> control flow successors for<br />

basic block B is denoted as Succ(B).<br />

Algorithm 3 gives <strong>the</strong> pseudo-code for <strong>the</strong> classical SSA<br />

renaming algorithm due to Cytron et al.<br />

2.2.2 Parallelization Strategy<br />

The sequential renaming algorithm presented in Algorithm<br />

3 cannot easily be parallelized using <strong>the</strong> same strategy as for<br />

<strong>the</strong> φ-insertion algorithm, i.e. one thread per variable. Such<br />

per-variable parallelism is not appropriate for <strong>the</strong> renaming<br />

phase, since each thread would have to process each statement,<br />

and would only perform a trivial amount <strong>of</strong> work at<br />

that statement. Fur<strong>the</strong>rmore, many variables may not be in<br />

scope for large parts <strong>of</strong> <strong>the</strong> program.<br />

Algorithm 3 Classical SSA renaming algorithm<br />

1: for all V : variables in original program do<br />

2: Count(V ) ← 0<br />

3: S(V ) ← EmptyStack<br />

4: end for<br />

5: call Search(EntryNode)<br />

6:<br />

7: procedure Search(X : BasicBlock)<br />

8: for all A : statement in X do<br />

9: if A is not a φ-function <strong>the</strong>n<br />

10: for all u : variables used in A do<br />

11: replace use <strong>of</strong> u with S(u) in A<br />

12: end for<br />

13: end if<br />

14: for all v : variables defined in A do<br />

15: i ← Count(v)<br />

16: replace definition <strong>of</strong> v with vi in A<br />

17: push vi onto S(v)<br />

18: Count(v) ← i + 1<br />

19: end for<br />

20: end for<br />

21: for all Y ∈ Succ(X) do<br />

22: let j be <strong>the</strong> index <strong>of</strong> <strong>the</strong> φ-function operands in Y<br />

that correspond to basic block X<br />

23: for all F : φ-function in Y do<br />

24: let V be <strong>the</strong> jth operand in F<br />

25: replace V with S(V ) at <strong>the</strong> jth operand in F<br />

26: end for<br />

27: end for<br />

28: for all Z ∈ Children(X) do<br />

29: call Search(Z)<br />

30: end for<br />

31: for all A : statements in X do<br />

32: for all Vi : variables defined in A do<br />

33: let V be <strong>the</strong> original variable corresponding to Vi<br />

34: pop S(V )<br />

35: end for<br />

36: end for<br />

37: end procedure

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!