Simplify constant unops
[smatch.git] / liveness.c
blob2ae6f112fa4bd4f4e93e6894ca48f632420aabd8
1 /*
2 * Register - track pseudo usage, maybe eventually try to do register
3 * allocation.
5 * Copyright (C) 2004 Linus Torvalds
6 */
8 #include <assert.h>
10 #include "parse.h"
11 #include "expression.h"
12 #include "linearize.h"
13 #include "flow.h"
15 static void phi_defines(struct instruction * phi_node, pseudo_t target,
16 void (*defines)(struct basic_block *, struct instruction *, pseudo_t))
18 pseudo_t phi;
19 FOR_EACH_PTR(phi_node->phi_list, phi) {
20 struct instruction *def;
21 if (phi == VOID)
22 continue;
23 def = phi->def;
24 if (!def || !def->bb)
25 continue;
26 if (def->opcode == OP_PHI) {
27 phi_defines(def, target, defines);
28 continue;
30 defines(def->bb, phi->def, target);
31 } END_FOR_EACH_PTR(phi);
34 static void track_instruction_usage(struct basic_block *bb, struct instruction *insn,
35 void (*def)(struct basic_block *, struct instruction *, pseudo_t),
36 void (*use)(struct basic_block *, struct instruction *, pseudo_t))
38 pseudo_t pseudo;
40 #define USES(x) use(bb, insn, insn->x)
41 #define DEFINES(x) def(bb, insn, insn->x)
43 switch (insn->opcode) {
44 case OP_RET:
45 USES(src);
46 break;
48 case OP_BR: case OP_SWITCH:
49 USES(cond);
50 break;
52 case OP_COMPUTEDGOTO:
53 USES(target);
54 break;
56 /* Binary */
57 case OP_BINARY ... OP_BINARY_END:
58 case OP_BINCMP ... OP_BINCMP_END:
59 USES(src1); USES(src2); DEFINES(target);
60 break;
62 /* Uni */
63 case OP_NOT: case OP_NEG:
64 USES(src1); DEFINES(target);
65 break;
67 case OP_SEL:
68 USES(src1); USES(src2); USES(src3); DEFINES(target);
69 break;
71 /* Memory */
72 case OP_LOAD:
73 USES(src); DEFINES(target);
74 break;
76 case OP_STORE:
77 USES(src); USES(target);
78 break;
80 case OP_SETVAL:
81 USES(symbol); DEFINES(target);
82 break;
84 /* Other */
85 case OP_PHI:
86 /* Phi-nodes are "backwards" nodes. Their def doesn't matter */
87 phi_defines(insn, insn->target, def);
88 break;
90 case OP_PHISOURCE:
92 * We don't care about the phi-source define, they get set
93 * up and expanded by the OP_PHI
95 USES(src1);
96 break;
98 case OP_CAST:
99 case OP_PTRCAST:
100 USES(src); DEFINES(target);
101 break;
103 case OP_CALL:
104 USES(func);
105 if (insn->target != VOID)
106 DEFINES(target);
107 FOR_EACH_PTR(insn->arguments, pseudo) {
108 use(bb, insn, pseudo);
109 } END_FOR_EACH_PTR(pseudo);
110 break;
112 case OP_SLICE:
113 USES(base); DEFINES(target);
114 break;
116 case OP_ASM:
117 FOR_EACH_PTR(insn->inputs, pseudo) {
118 use(bb, insn, pseudo);
119 } END_FOR_EACH_PTR(pseudo);
121 FOR_EACH_PTR(insn->outputs, pseudo) {
122 def(bb, insn, pseudo);
123 } END_FOR_EACH_PTR(pseudo);
124 break;
126 case OP_BADOP:
127 case OP_INVOKE:
128 case OP_UNWIND:
129 case OP_MALLOC:
130 case OP_FREE:
131 case OP_ALLOCA:
132 case OP_GET_ELEMENT_PTR:
133 case OP_VANEXT:
134 case OP_VAARG:
135 case OP_SNOP:
136 case OP_LNOP:
137 case OP_NOP:
138 case OP_CONTEXT:
139 break;
143 int pseudo_in_list(struct pseudo_list *list, pseudo_t pseudo)
145 pseudo_t old;
146 FOR_EACH_PTR(list,old) {
147 if (old == pseudo)
148 return 1;
149 } END_FOR_EACH_PTR(old);
150 return 0;
153 static int liveness_changed;
155 static void add_pseudo_exclusive(struct pseudo_list **list, pseudo_t pseudo)
157 if (!pseudo_in_list(*list, pseudo)) {
158 liveness_changed = 1;
159 add_pseudo(list, pseudo);
163 static inline int trackable_pseudo(pseudo_t pseudo)
165 return pseudo && (pseudo->type == PSEUDO_REG || pseudo->type == PSEUDO_PHI || pseudo->type == PSEUDO_ARG);
168 static void insn_uses(struct basic_block *bb, struct instruction *insn, pseudo_t pseudo)
170 if (trackable_pseudo(pseudo))
171 add_pseudo_exclusive(&bb->needs, pseudo);
174 static void insn_defines(struct basic_block *bb, struct instruction *insn, pseudo_t pseudo)
176 assert(trackable_pseudo(pseudo));
177 add_pseudo(&bb->defines, pseudo);
180 static void track_bb_liveness(struct basic_block *bb)
182 pseudo_t needs;
184 FOR_EACH_PTR(bb->needs, needs) {
185 if (!pseudo_in_list(bb->defines, needs)) {
186 struct basic_block *parent;
187 FOR_EACH_PTR(bb->parents, parent) {
188 if (!pseudo_in_list(parent->defines, needs)) {
189 add_pseudo_exclusive(&parent->needs, needs);
191 } END_FOR_EACH_PTR(parent);
193 } END_FOR_EACH_PTR(needs);
196 static inline void remove_pseudo(struct pseudo_list **list, pseudo_t pseudo)
198 delete_ptr_list_entry((struct ptr_list **)list, pseudo, 0);
202 * We need to clear the liveness information if we
203 * are going to re-run it.
205 void clear_liveness(struct entrypoint *ep)
207 struct basic_block *bb;
209 FOR_EACH_PTR(ep->bbs, bb) {
210 free_ptr_list(&bb->needs);
211 free_ptr_list(&bb->defines);
212 } END_FOR_EACH_PTR(bb);
216 * Track inter-bb pseudo liveness. The intra-bb case
217 * is purely local information.
219 void track_pseudo_liveness(struct entrypoint *ep)
221 struct basic_block *bb;
223 /* Add all the bb pseudo usage */
224 FOR_EACH_PTR(ep->bbs, bb) {
225 struct instruction *insn;
226 FOR_EACH_PTR(bb->insns, insn) {
227 if (!insn->bb)
228 continue;
229 assert(insn->bb == bb);
230 track_instruction_usage(bb, insn, insn_defines, insn_uses);
231 } END_FOR_EACH_PTR(insn);
232 } END_FOR_EACH_PTR(bb);
234 /* Remove the pseudos from the "need" list that are defined internally */
235 FOR_EACH_PTR(ep->bbs, bb) {
236 pseudo_t def;
237 FOR_EACH_PTR(bb->defines, def) {
238 remove_pseudo(&bb->needs, def);
239 } END_FOR_EACH_PTR(def);
240 } END_FOR_EACH_PTR(bb);
242 /* Calculate liveness.. */
243 do {
244 liveness_changed = 0;
245 FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
246 track_bb_liveness(bb);
247 } END_FOR_EACH_PTR_REVERSE(bb);
248 } while (liveness_changed);
250 /* Remove the pseudos from the "defines" list that are used internally */
251 FOR_EACH_PTR(ep->bbs, bb) {
252 pseudo_t def;
253 FOR_EACH_PTR(bb->defines, def) {
254 struct basic_block *child;
255 FOR_EACH_PTR(bb->children, child) {
256 if (pseudo_in_list(child->needs, def))
257 goto is_used;
258 } END_FOR_EACH_PTR(child);
259 DELETE_CURRENT_PTR(def);
260 is_used:
262 } END_FOR_EACH_PTR(def);
263 PACK_PTR_LIST(&bb->defines);
264 } END_FOR_EACH_PTR(bb);
267 static void merge_pseudo_list(struct pseudo_list *src, struct pseudo_list **dest)
269 pseudo_t pseudo;
270 FOR_EACH_PTR(src, pseudo) {
271 add_pseudo_exclusive(dest, pseudo);
272 } END_FOR_EACH_PTR(pseudo);
275 static struct pseudo_list **live_list;
276 static struct pseudo_list *dead_list;
278 static void death_def(struct basic_block *bb, struct instruction *insn, pseudo_t pseudo)
282 static void death_use(struct basic_block *bb, struct instruction *insn, pseudo_t pseudo)
284 if (trackable_pseudo(pseudo) && !pseudo_in_list(*live_list, pseudo)) {
285 add_pseudo(&dead_list, pseudo);
286 add_pseudo(live_list, pseudo);
290 static void track_pseudo_death_bb(struct basic_block *bb)
292 struct pseudo_list *live = NULL;
293 struct basic_block *child;
294 struct instruction *insn;
296 FOR_EACH_PTR(bb->children, child) {
297 merge_pseudo_list(child->needs, &live);
298 } END_FOR_EACH_PTR(child);
300 live_list = &live;
301 FOR_EACH_PTR_REVERSE(bb->insns, insn) {
302 if (!insn->bb)
303 continue;
304 dead_list = NULL;
305 track_instruction_usage(bb, insn, death_def, death_use);
306 if (dead_list) {
307 pseudo_t dead;
308 FOR_EACH_PTR(dead_list, dead) {
309 struct instruction *deathnote = __alloc_instruction(0);
310 deathnote->bb = bb;
311 deathnote->opcode = OP_DEATHNOTE;
312 deathnote->target = dead;
313 INSERT_CURRENT(deathnote, insn);
314 } END_FOR_EACH_PTR(dead);
315 free_ptr_list(&dead_list);
317 } END_FOR_EACH_PTR_REVERSE(insn);
318 free_ptr_list(&live);
321 void track_pseudo_death(struct entrypoint *ep)
323 struct basic_block *bb;
325 FOR_EACH_PTR(ep->bbs, bb) {
326 track_pseudo_death_bb(bb);
327 } END_FOR_EACH_PTR(bb);