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"
31 static struct instruction
*alloc_copy_insn(struct instruction
*phisrc
)
33 struct instruction
*insn
= __alloc_instruction(0);
34 insn
->opcode
= OP_COPY
;
35 insn
->size
= phisrc
->size
;
36 insn
->pos
= phisrc
->pos
;
40 // Is there a better way to do this ???
41 static void insert_insn_before(struct instruction
*old
, struct instruction
*new)
43 struct instruction
*insn
;
45 FOR_EACH_PTR_REVERSE(old
->bb
->insns
, insn
) {
47 INSERT_CURRENT(new, insn
);
49 END_FOR_EACH_PTR_REVERSE(insn
);
52 static void insert_copy(struct instruction
*phisrc
, pseudo_t tmp
)
54 struct instruction
*cpy
;
56 assert(phisrc
->opcode
== OP_PHISOURCE
);
58 cpy
= alloc_copy_insn(phisrc
);
60 cpy
->src
= phisrc
->phi_src
;
62 insert_insn_before(phisrc
, cpy
);
65 static void copy_phi_args(struct instruction
*phi
, struct pseudo_list
**list
)
67 pseudo_t tmp
, orig
= phi
->target
;
70 tmp
= alloc_pseudo(NULL
);
71 tmp
->type
= orig
->type
;
72 tmp
->def
= phi
; // wrongly set to the phi-node !!!
74 add_pseudo(list
, tmp
);
76 FOR_EACH_PTR(phi
->phi_list
, phisrc
) {
79 insert_copy(phisrc
->def
, tmp
);
80 } END_FOR_EACH_PTR(phisrc
);
83 static void unssa_bb(struct basic_block
*bb
)
85 struct pseudo_list
*list
= NULL
;
87 struct instruction
*insn
;
89 // copy all the phi nodes arguments to a new temporary pseudo
90 FOR_EACH_PTR(bb
->insns
, insn
) {
91 if (insn
->opcode
!= OP_PHI
)
93 copy_phi_args(insn
, &list
);
94 } END_FOR_EACH_PTR(insn
);
96 // now replace all the phi nodes themselves by copies of the
97 // temporaries to the phi nodes targets
98 FOR_EACH_PTR(list
, tmp
) {
99 struct instruction
*phi
= tmp
->def
;
101 phi
->opcode
= OP_COPY
;
103 } END_FOR_EACH_PTR(tmp
);
104 free_ptr_list(&list
);
107 int unssa(struct entrypoint
*ep
)
109 struct basic_block
*bb
;
111 FOR_EACH_PTR(ep
->bbs
, bb
) {
113 } END_FOR_EACH_PTR(bb
);