2 * Register - track pseudo usage, maybe eventually try to do register
5 * Copyright (C) 2004 Linus Torvalds
11 #include "expression.h"
12 #include "linearize.h"
15 static void phi_defines(struct instruction
* phi_node
, pseudo_t target
,
16 void (*defines
)(struct basic_block
*, pseudo_t
))
19 FOR_EACH_PTR(phi_node
->phi_list
, phi
) {
20 struct instruction
*def
;
26 defines(def
->bb
, target
);
27 } END_FOR_EACH_PTR(phi
);
30 static void asm_liveness(struct basic_block
*bb
, struct instruction
*insn
,
31 void (*def
)(struct basic_block
*, pseudo_t
),
32 void (*use
)(struct basic_block
*, pseudo_t
))
34 struct asm_constraint
*entry
;
36 FOR_EACH_PTR(insn
->asm_rules
->inputs
, entry
) {
37 use(bb
, entry
->pseudo
);
38 } END_FOR_EACH_PTR(entry
);
40 FOR_EACH_PTR(insn
->asm_rules
->outputs
, entry
) {
41 def(bb
, entry
->pseudo
);
42 } END_FOR_EACH_PTR(entry
);
45 static void track_instruction_usage(struct basic_block
*bb
, struct instruction
*insn
,
46 void (*def
)(struct basic_block
*, pseudo_t
),
47 void (*use
)(struct basic_block
*, pseudo_t
))
51 #define USES(x) use(bb, insn->x)
52 #define DEFINES(x) def(bb, insn->x)
54 switch (insn
->opcode
) {
69 case OP_BINARY
... OP_BINARY_END
:
70 case OP_BINCMP
... OP_BINCMP_END
:
71 USES(src1
); USES(src2
); DEFINES(target
);
75 case OP_NOT
: case OP_NEG
:
76 USES(src1
); DEFINES(target
);
80 USES(src1
); USES(src2
); USES(src3
); DEFINES(target
);
85 USES(src
); DEFINES(target
);
89 USES(src
); USES(target
);
97 USES(symbol
); DEFINES(target
);
102 /* Phi-nodes are "backwards" nodes. Their def doesn't matter */
103 phi_defines(insn
, insn
->target
, def
);
108 * We don't care about the phi-source define, they get set
109 * up and expanded by the OP_PHI
118 USES(src
); DEFINES(target
);
123 if (insn
->target
!= VOID
)
125 FOR_EACH_PTR(insn
->arguments
, pseudo
) {
127 } END_FOR_EACH_PTR(pseudo
);
131 USES(base
); DEFINES(target
);
135 asm_liveness(bb
, insn
, def
, use
);
139 USES(src1
); USES(src2
); USES(src3
);
148 case OP_GET_ELEMENT_PTR
:
159 int pseudo_in_list(struct pseudo_list
*list
, pseudo_t pseudo
)
162 FOR_EACH_PTR(list
,old
) {
165 } END_FOR_EACH_PTR(old
);
169 static int liveness_changed
;
171 static void add_pseudo_exclusive(struct pseudo_list
**list
, pseudo_t pseudo
)
173 if (!pseudo_in_list(*list
, pseudo
)) {
174 liveness_changed
= 1;
175 add_pseudo(list
, pseudo
);
179 static inline int trackable_pseudo(pseudo_t pseudo
)
181 return pseudo
&& (pseudo
->type
== PSEUDO_REG
|| pseudo
->type
== PSEUDO_ARG
);
184 static void insn_uses(struct basic_block
*bb
, pseudo_t pseudo
)
186 if (trackable_pseudo(pseudo
)) {
187 struct instruction
*def
= pseudo
->def
;
188 if (pseudo
->type
!= PSEUDO_REG
|| def
->bb
!= bb
|| def
->opcode
== OP_PHI
)
189 add_pseudo_exclusive(&bb
->needs
, pseudo
);
193 static void insn_defines(struct basic_block
*bb
, pseudo_t pseudo
)
195 assert(trackable_pseudo(pseudo
));
196 add_pseudo(&bb
->defines
, pseudo
);
199 static void track_bb_liveness(struct basic_block
*bb
)
203 FOR_EACH_PTR(bb
->needs
, needs
) {
204 struct basic_block
*parent
;
205 FOR_EACH_PTR(bb
->parents
, parent
) {
206 if (!pseudo_in_list(parent
->defines
, needs
)) {
207 add_pseudo_exclusive(&parent
->needs
, needs
);
209 } END_FOR_EACH_PTR(parent
);
210 } END_FOR_EACH_PTR(needs
);
214 * We need to clear the liveness information if we
215 * are going to re-run it.
217 void clear_liveness(struct entrypoint
*ep
)
219 struct basic_block
*bb
;
221 FOR_EACH_PTR(ep
->bbs
, bb
) {
222 free_ptr_list(&bb
->needs
);
223 free_ptr_list(&bb
->defines
);
224 } END_FOR_EACH_PTR(bb
);
228 * Track inter-bb pseudo liveness. The intra-bb case
229 * is purely local information.
231 void track_pseudo_liveness(struct entrypoint
*ep
)
233 struct basic_block
*bb
;
235 /* Add all the bb pseudo usage */
236 FOR_EACH_PTR(ep
->bbs
, bb
) {
237 struct instruction
*insn
;
238 FOR_EACH_PTR(bb
->insns
, insn
) {
241 assert(insn
->bb
== bb
);
242 track_instruction_usage(bb
, insn
, insn_defines
, insn_uses
);
243 } END_FOR_EACH_PTR(insn
);
244 } END_FOR_EACH_PTR(bb
);
246 /* Calculate liveness.. */
248 liveness_changed
= 0;
249 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
250 track_bb_liveness(bb
);
251 } END_FOR_EACH_PTR_REVERSE(bb
);
252 } while (liveness_changed
);
254 /* Remove the pseudos from the "defines" list that are used internally */
255 FOR_EACH_PTR(ep
->bbs
, bb
) {
257 FOR_EACH_PTR(bb
->defines
, def
) {
258 struct basic_block
*child
;
259 FOR_EACH_PTR(bb
->children
, child
) {
260 if (pseudo_in_list(child
->needs
, def
))
262 } END_FOR_EACH_PTR(child
);
263 DELETE_CURRENT_PTR(def
);
266 } END_FOR_EACH_PTR(def
);
267 PACK_PTR_LIST(&bb
->defines
);
268 } END_FOR_EACH_PTR(bb
);
271 static void merge_pseudo_list(struct pseudo_list
*src
, struct pseudo_list
**dest
)
274 FOR_EACH_PTR(src
, pseudo
) {
275 add_pseudo_exclusive(dest
, pseudo
);
276 } END_FOR_EACH_PTR(pseudo
);
279 void track_phi_uses(struct instruction
*insn
)
282 FOR_EACH_PTR(insn
->phi_list
, phi
) {
283 struct instruction
*def
;
284 if (phi
== VOID
|| !phi
->def
)
287 assert(def
->opcode
== OP_PHISOURCE
);
288 add_ptr_list(&def
->phi_users
, insn
);
289 } END_FOR_EACH_PTR(phi
);
292 static void track_bb_phi_uses(struct basic_block
*bb
)
294 struct instruction
*insn
;
295 FOR_EACH_PTR(bb
->insns
, insn
) {
296 if (insn
->bb
&& insn
->opcode
== OP_PHI
)
297 track_phi_uses(insn
);
298 } END_FOR_EACH_PTR(insn
);
301 static struct pseudo_list
**live_list
;
302 static struct pseudo_list
*dead_list
;
304 static void death_def(struct basic_block
*bb
, pseudo_t pseudo
)
308 static void death_use(struct basic_block
*bb
, pseudo_t pseudo
)
310 if (trackable_pseudo(pseudo
) && !pseudo_in_list(*live_list
, pseudo
)) {
311 add_pseudo(&dead_list
, pseudo
);
312 add_pseudo(live_list
, pseudo
);
316 static void track_pseudo_death_bb(struct basic_block
*bb
)
318 struct pseudo_list
*live
= NULL
;
319 struct basic_block
*child
;
320 struct instruction
*insn
;
322 FOR_EACH_PTR(bb
->children
, child
) {
323 merge_pseudo_list(child
->needs
, &live
);
324 } END_FOR_EACH_PTR(child
);
327 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
332 track_instruction_usage(bb
, insn
, death_def
, death_use
);
335 FOR_EACH_PTR(dead_list
, dead
) {
336 struct instruction
*deathnote
= __alloc_instruction(0);
338 deathnote
->opcode
= OP_DEATHNOTE
;
339 deathnote
->target
= dead
;
340 INSERT_CURRENT(deathnote
, insn
);
341 } END_FOR_EACH_PTR(dead
);
342 free_ptr_list(&dead_list
);
344 } END_FOR_EACH_PTR_REVERSE(insn
);
345 free_ptr_list(&live
);
348 void track_pseudo_death(struct entrypoint
*ep
)
350 struct basic_block
*bb
;
352 FOR_EACH_PTR(ep
->bbs
, bb
) {
353 track_bb_phi_uses(bb
);
354 } END_FOR_EACH_PTR(bb
);
356 FOR_EACH_PTR(ep
->bbs
, bb
) {
357 track_pseudo_death_bb(bb
);
358 } END_FOR_EACH_PTR(bb
);