6 struct ssavar
*alloc_variable (struct basicblock
*block
)
9 var
= fixedpool_alloc (block
->sub
->code
->ssavarspool
);
10 var
->uses
= list_alloc (block
->sub
->code
->lstpool
);
15 void ssa_place_phis (struct subroutine
*sub
, list
*defblocks
)
17 struct basicblock
*block
, *bref
;
18 struct basicblocknode
*brefnode
;
22 el
= list_head (sub
->blocks
);
24 block
= element_getvalue (el
);
27 el
= element_next (el
);
30 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
31 list worklist
= defblocks
[regno
];
32 el
= list_head (worklist
);
34 block
= element_getvalue (el
);
36 el
= element_next (el
);
39 while (list_size (worklist
) != 0) {
40 block
= list_removehead (worklist
);
41 ref
= list_head (block
->node
.frontier
);
43 brefnode
= element_getvalue (ref
);
44 bref
= element_getvalue (brefnode
->blockel
);
45 if (bref
->mark2
!= regno
&& IS_BIT_SET (bref
->reg_live_out
, regno
)) {
49 op
= operation_alloc (bref
);
51 value_append (sub
, op
->results
, VAL_REGISTER
, regno
);
52 for (i
= list_size (bref
->inrefs
); i
> 0; i
--)
53 value_append (sub
, op
->operands
, VAL_REGISTER
, regno
);
54 list_inserthead (bref
->operations
, op
);
56 if (bref
->mark1
!= regno
) {
58 list_inserttail (worklist
, bref
);
61 ref
= element_next (ref
);
68 void ssa_search (struct basicblock
*block
, list
*vars
)
71 int regno
, pushed
[NUM_REGISTERS
];
73 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++)
74 pushed
[regno
] = FALSE
;
76 el
= list_head (block
->operations
);
83 op
= element_getvalue (el
);
85 if (op
->type
!= OP_PHI
) {
86 opel
= list_head (op
->operands
);
88 val
= element_getvalue (opel
);
89 if (val
->type
== VAL_REGISTER
) {
90 var
= list_headvalue (vars
[val
->val
.intval
]);
91 val
->type
= VAL_SSAVAR
;
92 val
->val
.variable
= var
;
93 list_inserttail (var
->uses
, op
);
95 opel
= element_next (opel
);
99 rel
= list_head (op
->results
);
101 val
= element_getvalue (rel
);
102 if (val
->type
== VAL_REGISTER
) {
103 val
->type
= VAL_SSAVAR
;
104 var
= alloc_variable (block
);
105 var
->name
.type
= VAL_REGISTER
;
106 var
->name
.val
.intval
= val
->val
.intval
;
108 list_inserttail (block
->sub
->ssavars
, var
);
109 if (!pushed
[val
->val
.intval
]) {
110 pushed
[val
->val
.intval
] = TRUE
;
111 list_inserthead (vars
[val
->val
.intval
], var
);
113 element_setvalue (list_head (vars
[val
->val
.intval
]), var
);
115 val
->val
.variable
= var
;
117 rel
= element_next (rel
);
120 el
= element_next (el
);
123 el
= list_head (block
->outrefs
);
125 struct basicedge
*edge
;
126 struct basicblock
*ref
;
129 edge
= element_getvalue (el
);
132 phiel
= list_head (ref
->operations
);
134 struct operation
*op
;
137 op
= element_getvalue (phiel
);
138 if (op
->type
!= OP_PHI
) break;
140 opel
= list_head (op
->operands
);
141 for (regno
= edge
->tonum
; regno
> 0; regno
--)
142 opel
= element_next (opel
);
144 val
= element_getvalue (opel
);
145 val
->type
= VAL_SSAVAR
;
146 val
->val
.variable
= list_headvalue (vars
[val
->val
.intval
]);
147 list_inserttail (val
->val
.variable
->uses
, op
);
148 phiel
= element_next (phiel
);
150 el
= element_next (el
);
153 el
= list_head (block
->node
.children
);
155 struct basicblocknode
*childnode
;
156 struct basicblock
*child
;
158 childnode
= element_getvalue (el
);
159 child
= element_getvalue (childnode
->blockel
);
160 ssa_search (child
, vars
);
161 el
= element_next (el
);
164 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++)
165 if (pushed
[regno
]) list_removehead (vars
[regno
]);
168 void build_ssa (struct subroutine
*sub
)
170 list reglist
[NUM_REGISTERS
];
175 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
176 reglist
[regno
] = list_alloc (sub
->code
->lstpool
);
179 sub
->ssavars
= list_alloc (sub
->code
->lstpool
);
181 blockel
= list_head (sub
->blocks
);
183 struct basicblock
*block
= element_getvalue (blockel
);
184 for (regno
= 0; regno
< NUM_REGISTERS
; regno
++) {
185 if (IS_BIT_SET (block
->reg_kill
, regno
))
186 list_inserttail (reglist
[regno
], block
);
188 blockel
= element_next (blockel
);
191 ssa_place_phis (sub
, reglist
);
192 ssa_search (sub
->startblock
, reglist
);
194 for (regno
= 1; regno
< NUM_REGISTERS
; regno
++) {
195 list_free (reglist
[regno
]);
199 void unbuild_ssa (struct subroutine
*sub
)
201 element varel
, valel
, blockel
, opel
;
203 blockel
= list_head (sub
->blocks
);
205 struct basicblock
*block
= element_getvalue (blockel
);
206 opel
= list_head (block
->operations
);
208 struct operation
*op
= element_getvalue (opel
);
211 nextopel
= element_next (opel
);
212 if (op
->type
== OP_PHI
) {
213 element_remove (opel
);
215 valel
= list_head (op
->operands
);
217 struct value
*val
= element_getvalue (valel
);
218 fixedpool_free (sub
->code
->valspool
, val
);
219 valel
= element_next (valel
);
221 list_free (op
->operands
);
223 fixedpool_free (sub
->code
->valspool
, list_headvalue (op
->results
));
224 list_free (op
->results
);
226 valel
= list_head (op
->operands
);
228 struct value
*val
= element_getvalue (valel
);
229 if (val
->type
== VAL_SSAVAR
) {
230 val
->type
= VAL_REGISTER
;
231 val
->val
.intval
= val
->val
.variable
->name
.val
.intval
;
233 valel
= element_next (valel
);
236 valel
= list_head (op
->results
);
238 struct value
*val
= element_getvalue (valel
);
239 if (val
->type
== VAL_SSAVAR
) {
240 val
->type
= VAL_REGISTER
;
241 val
->val
.intval
= val
->val
.variable
->name
.val
.intval
;
243 valel
= element_next (valel
);
249 blockel
= element_next (blockel
);
252 varel
= list_head (sub
->ssavars
);
254 struct ssavar
*var
= element_getvalue (varel
);
255 list_free (var
->uses
);
256 fixedpool_free (sub
->code
->ssavarspool
, var
);
257 varel
= element_next (varel
);
259 list_free (sub
->ssavars
);