2 * Author: Humberto Naves (hsnaves@gmail.com)
9 struct ssavar
*alloc_variable (struct basicblock
*block
)
12 var
= fixedpool_alloc (block
->sub
->code
->ssavarspool
);
13 var
->uses
= list_alloc (block
->sub
->code
->lstpool
);
18 void ssa_place_phis (struct subroutine
*sub
, list
*defblocks
)
20 struct basicblock
*block
, *bref
;
21 struct basicblocknode
*brefnode
;
25 el
= list_head (sub
->blocks
);
27 block
= element_getvalue (el
);
30 el
= element_next (el
);
33 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
34 list worklist
= defblocks
[regno
];
35 el
= list_head (worklist
);
37 block
= element_getvalue (el
);
39 el
= element_next (el
);
42 while (list_size (worklist
) != 0) {
43 block
= list_removehead (worklist
);
44 ref
= list_head (block
->node
.frontier
);
46 brefnode
= element_getvalue (ref
);
47 bref
= element_getvalue (brefnode
->blockel
);
48 if (bref
->mark2
!= regno
&& IS_BIT_SET (bref
->reg_live_out
, regno
)) {
52 op
= operation_alloc (bref
);
54 value_append (sub
, op
->results
, VAL_REGISTER
, regno
, FALSE
);
55 for (i
= list_size (bref
->inrefs
); i
> 0; i
--)
56 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
, FALSE
);
57 list_inserthead (bref
->operations
, op
);
59 if (bref
->mark1
!= regno
) {
61 list_inserttail (worklist
, bref
);
64 ref
= element_next (ref
);
71 void ssa_search (struct basicblock
*block
, list
*vars
)
74 int regno
, pushed
[NUM_REGISTERS
];
76 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++)
77 pushed
[regno
] = FALSE
;
79 el
= list_head (block
->operations
);
86 op
= element_getvalue (el
);
88 if (op
->type
!= OP_PHI
) {
89 opel
= list_head (op
->operands
);
91 val
= element_getvalue (opel
);
92 if (val
->type
== VAL_REGISTER
) {
93 var
= list_headvalue (vars
[val
->val
.intval
]);
94 val
->type
= VAL_SSAVAR
;
95 val
->val
.variable
= var
;
96 if (op
->type
== OP_ASM
)
97 var
->status
|= VAR_STAT_ASMARG
;
98 list_inserttail (var
->uses
, op
);
100 opel
= element_next (opel
);
104 rel
= list_head (op
->results
);
106 val
= element_getvalue (rel
);
107 if (val
->type
== VAL_REGISTER
) {
108 val
->type
= VAL_SSAVAR
;
109 var
= alloc_variable (block
);
110 var
->name
.type
= VAL_REGISTER
;
111 var
->name
.val
.intval
= val
->val
.intval
;
113 list_inserttail (block
->sub
->ssavars
, var
);
114 if (!pushed
[val
->val
.intval
]) {
115 pushed
[val
->val
.intval
] = TRUE
;
116 list_inserthead (vars
[val
->val
.intval
], var
);
118 element_setvalue (list_head (vars
[val
->val
.intval
]), var
);
120 val
->val
.variable
= var
;
122 rel
= element_next (rel
);
125 el
= element_next (el
);
128 el
= list_head (block
->outrefs
);
130 struct basicedge
*edge
;
131 struct basicblock
*ref
;
134 edge
= element_getvalue (el
);
137 phiel
= list_head (ref
->operations
);
139 struct operation
*op
;
143 op
= element_getvalue (phiel
);
144 if (op
->type
!= OP_PHI
) break;
146 opel
= list_head (op
->operands
);
147 for (regno
= edge
->tonum
; regno
> 0; regno
--)
148 opel
= element_next (opel
);
150 val
= element_getvalue (opel
);
151 val
->type
= VAL_SSAVAR
;
152 var
= val
->val
.variable
= list_headvalue (vars
[val
->val
.intval
]);
153 var
->status
|= VAR_STAT_PHIARG
;
154 list_inserttail (var
->uses
, op
);
155 phiel
= element_next (phiel
);
157 el
= element_next (el
);
160 el
= list_head (block
->node
.children
);
162 struct basicblocknode
*childnode
;
163 struct basicblock
*child
;
165 childnode
= element_getvalue (el
);
166 child
= element_getvalue (childnode
->blockel
);
167 ssa_search (child
, vars
);
168 el
= element_next (el
);
171 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++)
172 if (pushed
[regno
]) list_removehead (vars
[regno
]);
175 void build_ssa (struct subroutine
*sub
)
177 list reglist
[NUM_REGISTERS
];
182 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
183 reglist
[regno
] = list_alloc (sub
->code
->lstpool
);
186 sub
->ssavars
= list_alloc (sub
->code
->lstpool
);
188 blockel
= list_head (sub
->blocks
);
190 struct basicblock
*block
= element_getvalue (blockel
);
191 for (regno
= 0; regno
< NUM_REGISTERS
; regno
++) {
192 if (IS_BIT_SET (block
->reg_kill
, regno
))
193 list_inserttail (reglist
[regno
], block
);
195 blockel
= element_next (blockel
);
198 ssa_place_phis (sub
, reglist
);
199 ssa_search (sub
->startblock
, reglist
);
201 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
202 list_free (reglist
[regno
]);
206 void unbuild_ssa (struct subroutine
*sub
)
208 element varel
, valel
, blockel
, opel
;
210 blockel
= list_head (sub
->blocks
);
212 struct basicblock
*block
= element_getvalue (blockel
);
213 opel
= list_head (block
->operations
);
215 struct operation
*op
= element_getvalue (opel
);
218 nextopel
= element_next (opel
);
219 if (op
->type
== OP_PHI
) {
220 element_remove (opel
);
222 valel
= list_head (op
->operands
);
224 struct value
*val
= element_getvalue (valel
);
225 fixedpool_free (sub
->code
->valspool
, val
);
226 valel
= element_next (valel
);
228 list_free (op
->operands
);
230 fixedpool_free (sub
->code
->valspool
, list_headvalue (op
->results
));
231 list_free (op
->results
);
233 valel
= list_head (op
->operands
);
235 struct value
*val
= element_getvalue (valel
);
236 if (val
->type
== VAL_SSAVAR
) {
237 val
->type
= VAL_REGISTER
;
238 val
->val
.intval
= val
->val
.variable
->name
.val
.intval
;
240 valel
= element_next (valel
);
243 valel
= list_head (op
->results
);
245 struct value
*val
= element_getvalue (valel
);
246 if (val
->type
== VAL_SSAVAR
) {
247 val
->type
= VAL_REGISTER
;
248 val
->val
.intval
= val
->val
.variable
->name
.val
.intval
;
250 valel
= element_next (valel
);
256 blockel
= element_next (blockel
);
259 varel
= list_head (sub
->ssavars
);
261 struct ssavar
*var
= element_getvalue (varel
);
262 list_free (var
->uses
);
263 fixedpool_free (sub
->code
->ssavarspool
, var
);
264 varel
= element_next (varel
);
266 list_free (sub
->ssavars
);