2 * Register - track pseudo usage, maybe eventually try to do register
5 * Copyright (C) 2004 Linus Torvalds
12 #include "expression.h"
13 #include "linearize.h"
16 static void phi_defines(struct instruction
* phi_node
, pseudo_t target
,
17 void (*defines
)(struct basic_block
*, pseudo_t
))
20 FOR_EACH_PTR(phi_node
->phi_list
, phi
) {
21 struct instruction
*def
;
27 defines(def
->bb
, target
);
28 } END_FOR_EACH_PTR(phi
);
31 static void asm_liveness(struct basic_block
*bb
, struct instruction
*insn
,
32 void (*def
)(struct basic_block
*, pseudo_t
),
33 void (*use
)(struct basic_block
*, pseudo_t
))
35 struct asm_constraint
*entry
;
37 FOR_EACH_PTR(insn
->asm_rules
->inputs
, entry
) {
38 use(bb
, entry
->pseudo
);
39 } END_FOR_EACH_PTR(entry
);
41 FOR_EACH_PTR(insn
->asm_rules
->outputs
, entry
) {
43 use(bb
, entry
->pseudo
);
45 def(bb
, entry
->pseudo
);
46 } END_FOR_EACH_PTR(entry
);
49 static void track_instruction_usage(struct basic_block
*bb
, struct instruction
*insn
,
50 void (*def
)(struct basic_block
*, pseudo_t
),
51 void (*use
)(struct basic_block
*, pseudo_t
))
55 #define USES(x) use(bb, insn->x)
56 #define DEFINES(x) def(bb, insn->x)
58 switch (insn
->opcode
) {
70 case OP_BINARY
... OP_BINARY_END
:
71 case OP_FPCMP
... OP_FPCMP_END
:
72 case OP_BINCMP
... OP_BINCMP_END
:
73 USES(src1
); USES(src2
); DEFINES(target
);
77 case OP_UNOP
... OP_UNOP_END
:
80 USES(src
); DEFINES(target
);
84 USES(src1
); USES(src2
); USES(src3
); DEFINES(target
);
89 USES(src
); DEFINES(target
);
93 USES(src
); USES(target
);
104 /* Phi-nodes are "backwards" nodes. Their def doesn't matter */
105 phi_defines(insn
, insn
->target
, def
);
110 * We don't care about the phi-source define, they get set
111 * up and expanded by the OP_PHI
118 if (insn
->target
!= VOID
)
120 FOR_EACH_PTR(insn
->arguments
, pseudo
) {
122 } END_FOR_EACH_PTR(pseudo
);
126 asm_liveness(bb
, insn
, def
, use
);
130 USES(src1
); USES(src2
); USES(src3
);
141 static int liveness_changed
;
143 static void add_pseudo_exclusive(struct pseudo_list
**list
, pseudo_t pseudo
)
145 if (!pseudo_in_list(*list
, pseudo
)) {
146 liveness_changed
= 1;
147 add_pseudo(list
, pseudo
);
151 static inline int trackable_pseudo(pseudo_t pseudo
)
153 return pseudo
&& (pseudo
->type
== PSEUDO_REG
|| pseudo
->type
== PSEUDO_ARG
);
156 static void insn_uses(struct basic_block
*bb
, pseudo_t pseudo
)
158 if (trackable_pseudo(pseudo
)) {
159 struct instruction
*def
= pseudo
->def
;
160 if (pseudo
->type
!= PSEUDO_REG
|| def
->bb
!= bb
|| def
->opcode
== OP_PHI
)
161 add_pseudo_exclusive(&bb
->needs
, pseudo
);
165 static void insn_defines(struct basic_block
*bb
, pseudo_t pseudo
)
167 assert(trackable_pseudo(pseudo
));
168 add_pseudo(&bb
->defines
, pseudo
);
171 static void track_bb_liveness(struct basic_block
*bb
)
175 FOR_EACH_PTR(bb
->needs
, needs
) {
176 struct basic_block
*parent
;
177 FOR_EACH_PTR(bb
->parents
, parent
) {
178 if (!pseudo_in_list(parent
->defines
, needs
)) {
179 add_pseudo_exclusive(&parent
->needs
, needs
);
181 } END_FOR_EACH_PTR(parent
);
182 } END_FOR_EACH_PTR(needs
);
186 * We need to clear the liveness information if we
187 * are going to re-run it.
189 void clear_liveness(struct entrypoint
*ep
)
191 struct basic_block
*bb
;
193 FOR_EACH_PTR(ep
->bbs
, bb
) {
194 free_ptr_list(&bb
->needs
);
195 free_ptr_list(&bb
->defines
);
196 } END_FOR_EACH_PTR(bb
);
200 * Track inter-bb pseudo liveness. The intra-bb case
201 * is purely local information.
203 void track_pseudo_liveness(struct entrypoint
*ep
)
205 struct basic_block
*bb
;
207 /* Add all the bb pseudo usage */
208 FOR_EACH_PTR(ep
->bbs
, bb
) {
209 struct instruction
*insn
;
210 FOR_EACH_PTR(bb
->insns
, insn
) {
213 assert(insn
->bb
== bb
);
214 track_instruction_usage(bb
, insn
, insn_defines
, insn_uses
);
215 } END_FOR_EACH_PTR(insn
);
216 } END_FOR_EACH_PTR(bb
);
218 /* Calculate liveness.. */
220 liveness_changed
= 0;
221 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
222 track_bb_liveness(bb
);
223 } END_FOR_EACH_PTR_REVERSE(bb
);
224 } while (liveness_changed
);
226 /* Remove the pseudos from the "defines" list that are used internally */
227 FOR_EACH_PTR(ep
->bbs
, bb
) {
229 FOR_EACH_PTR(bb
->defines
, def
) {
230 struct basic_block
*child
;
231 FOR_EACH_PTR(bb
->children
, child
) {
232 if (pseudo_in_list(child
->needs
, def
))
234 } END_FOR_EACH_PTR(child
);
235 DELETE_CURRENT_PTR(def
);
238 } END_FOR_EACH_PTR(def
);
239 PACK_PTR_LIST(&bb
->defines
);
240 } END_FOR_EACH_PTR(bb
);
243 static void merge_pseudo_list(struct pseudo_list
*src
, struct pseudo_list
**dest
)
246 FOR_EACH_PTR(src
, pseudo
) {
247 add_pseudo_exclusive(dest
, pseudo
);
248 } END_FOR_EACH_PTR(pseudo
);
251 static void track_phi_uses(struct instruction
*insn
)
254 FOR_EACH_PTR(insn
->phi_list
, phi
) {
255 struct instruction
*def
;
256 if (phi
== VOID
|| !phi
->def
)
259 assert(def
->opcode
== OP_PHISOURCE
);
260 } END_FOR_EACH_PTR(phi
);
263 static void track_bb_phi_uses(struct basic_block
*bb
)
265 struct instruction
*insn
;
266 FOR_EACH_PTR(bb
->insns
, insn
) {
267 if (insn
->bb
&& insn
->opcode
== OP_PHI
)
268 track_phi_uses(insn
);
269 } END_FOR_EACH_PTR(insn
);
272 static struct pseudo_list
**live_list
;
273 static struct pseudo_list
*dead_list
;
275 static void death_def(struct basic_block
*bb
, pseudo_t pseudo
)
279 static void death_use(struct basic_block
*bb
, pseudo_t pseudo
)
281 if (trackable_pseudo(pseudo
) && !pseudo_in_list(*live_list
, pseudo
)) {
282 add_pseudo(&dead_list
, pseudo
);
283 add_pseudo(live_list
, pseudo
);
287 static void track_pseudo_death_bb(struct basic_block
*bb
)
289 struct pseudo_list
*live
= NULL
;
290 struct basic_block
*child
;
291 struct instruction
*insn
;
293 FOR_EACH_PTR(bb
->children
, child
) {
294 merge_pseudo_list(child
->needs
, &live
);
295 } END_FOR_EACH_PTR(child
);
298 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
303 track_instruction_usage(bb
, insn
, death_def
, death_use
);
306 FOR_EACH_PTR(dead_list
, dead
) {
307 struct instruction
*deathnote
= __alloc_instruction(0);
309 deathnote
->opcode
= OP_DEATHNOTE
;
310 deathnote
->target
= dead
;
311 INSERT_CURRENT(deathnote
, insn
);
312 } END_FOR_EACH_PTR(dead
);
313 free_ptr_list(&dead_list
);
315 } END_FOR_EACH_PTR_REVERSE(insn
);
316 free_ptr_list(&live
);
319 void track_pseudo_death(struct entrypoint
*ep
)
321 struct basic_block
*bb
;
323 FOR_EACH_PTR(ep
->bbs
, bb
) {
324 track_bb_phi_uses(bb
);
325 } END_FOR_EACH_PTR(bb
);
327 FOR_EACH_PTR(ep
->bbs
, bb
) {
328 track_pseudo_death_bb(bb
);
329 } END_FOR_EACH_PTR(bb
);