2 * UnSSA - translate the SSA back to normal form.
4 * For now it's done by replacing to set of copies:
5 * 1) For each phi-node, replace all their phisrc by copies to a common
7 * 2) Replace all the phi-nodes by copies of the temporaries to the phi-node target.
8 * This is node to preserve the semantic of the phi-node (they should all "execute"
9 * simultaneously on entry in the basic block in which they belong).
11 * This is similar to the "Sreedhar method I" except that the copies to the
12 * temporaries are not placed at the end of the predecessor basic blocks, but
13 * at the place where the phi-node operands are defined (the same place where the
14 * phisrc were present).
17 * While very simple this method create a lot more copies that really necessary.
18 * Ideally, "Sreedhar method III" should be used:
19 * "Translating Out of Static Single Assignment Form", V. C. Sreedhar, R. D.-C. Ju,
20 * D. M. Gillies and V. Santhanam. SAS'99, Vol. 1694 of Lecture Notes in Computer
21 * Science, Springer-Verlag, pp. 194-210, 1999.
23 * Copyright (C) 2005 Luc Van Oostenryck
27 #include "linearize.h"
33 static void remove_phisrc_defines(struct instruction
*phisrc
)
35 struct instruction
*phi
;
36 struct basic_block
*bb
= phisrc
->bb
;
38 FOR_EACH_PTR(phisrc
->phi_users
, phi
) {
39 remove_pseudo(&bb
->defines
, phi
->target
);
40 } END_FOR_EACH_PTR(phi
);
43 static void replace_phi_node(struct instruction
*phi
)
47 tmp
= alloc_pseudo(NULL
);
48 tmp
->type
= phi
->target
->type
;
49 tmp
->ident
= phi
->target
->ident
;
50 tmp
->def
= NULL
; // defined by all the phisrc
52 // update the current liveness
53 remove_pseudo(&phi
->bb
->needs
, phi
->target
);
54 add_pseudo(&phi
->bb
->needs
, tmp
);
57 phi
->opcode
= OP_COPY
;
60 // FIXME: free phi->phi_list;
63 static void rewrite_phi_bb(struct basic_block
*bb
)
65 struct instruction
*insn
;
67 // Replace all the phi-nodes by copies of a temporary
68 // (which represent the set of all the %phi that feed them).
69 // The target pseudo doesn't change.
70 FOR_EACH_PTR(bb
->insns
, insn
) {
73 if (insn
->opcode
!= OP_PHI
)
75 replace_phi_node(insn
);
76 } END_FOR_EACH_PTR(insn
);
79 static void rewrite_phisrc_bb(struct basic_block
*bb
)
81 struct instruction
*insn
;
83 // Replace all the phisrc by one or several copies to
84 // the temporaries associated to each phi-node it defines.
85 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
86 struct instruction
*phi
;
91 if (insn
->opcode
!= OP_PHISOURCE
)
95 FOR_EACH_PTR(insn
->phi_users
, phi
) {
96 pseudo_t tmp
= phi
->src
;
97 pseudo_t src
= insn
->phi_src
;
99 if (i
== 0) { // first phi: we overwrite the phisrc
100 insn
->opcode
= OP_COPY
;
104 struct instruction
*copy
= __alloc_instruction(0);
107 copy
->opcode
= OP_COPY
;
108 copy
->size
= insn
->size
;
109 copy
->pos
= insn
->pos
;
113 INSERT_CURRENT(copy
, insn
);
115 // update the liveness info
116 remove_phisrc_defines(insn
);
117 // FIXME: should really something like add_pseudo_exclusive()
118 add_pseudo(&bb
->defines
, tmp
);
121 } END_FOR_EACH_PTR(phi
);
123 } END_FOR_EACH_PTR_REVERSE(insn
);
126 int unssa(struct entrypoint
*ep
)
128 struct basic_block
*bb
;
130 FOR_EACH_PTR(ep
->bbs
, bb
) {
132 } END_FOR_EACH_PTR(bb
);
134 FOR_EACH_PTR(ep
->bbs
, bb
) {
135 rewrite_phisrc_bb(bb
);
136 } END_FOR_EACH_PTR(bb
);