Rename "register.c" into "liveness.c". That's what it does.
[smatch.git] / cse.c
blob4de950d00497cf40c33a42596ff0682abfe4b665
1 /*
2 * CSE - walk the linearized instruction flow, and
3 * see if we can simplify it and apply CSE on it.
5 * Copyright (C) 2004 Linus Torvalds
6 */
8 #include <string.h>
9 #include <stdarg.h>
10 #include <stdlib.h>
11 #include <stdio.h>
12 #include <stddef.h>
13 #include <assert.h>
15 #include "parse.h"
16 #include "expression.h"
17 #include "linearize.h"
18 #include "flow.h"
20 #define INSN_HASH_SIZE 65536
21 static struct instruction_list *insn_hash_table[INSN_HASH_SIZE];
23 #define hashval(x) ((unsigned long)(x))
25 int repeat_phase, merge_phi_sources;
27 static int phi_compare(pseudo_t phi1, pseudo_t phi2)
29 const struct instruction *def1 = phi1->def;
30 const struct instruction *def2 = phi2->def;
32 if (def1->src1 != def2->src1)
33 return def1->src1 < def2->src1 ? -1 : 1;
34 if (def1->bb != def2->bb)
35 return def1->bb < def2->bb ? -1 : 1;
36 return 0;
40 static void clean_up_one_instruction(struct basic_block *bb, struct instruction *insn)
42 unsigned long hash;
44 if (!insn->bb)
45 return;
46 assert(insn->bb == bb);
47 repeat_phase |= simplify_instruction(insn);
48 hash = (insn->opcode << 3) + (insn->size >> 3);
49 switch (insn->opcode) {
51 /* Binary arithmetic */
52 case OP_ADD: case OP_SUB:
53 case OP_MUL: case OP_DIV:
54 case OP_MOD: case OP_SHL:
55 case OP_SHR:
56 case OP_AND: case OP_OR:
58 /* Binary logical */
59 case OP_XOR: case OP_AND_BOOL:
60 case OP_OR_BOOL:
62 /* Binary comparison */
63 case OP_SET_EQ: case OP_SET_NE:
64 case OP_SET_LE: case OP_SET_GE:
65 case OP_SET_LT: case OP_SET_GT:
66 case OP_SET_B: case OP_SET_A:
67 case OP_SET_BE: case OP_SET_AE:
68 hash += hashval(insn->src1);
69 hash += hashval(insn->src2);
70 break;
72 /* Unary */
73 case OP_NOT: case OP_NEG:
74 hash += hashval(insn->src1);
75 break;
77 case OP_SETVAL:
78 hash += hashval(insn->val);
79 hash += hashval(insn->symbol);
80 break;
82 /* Other */
83 case OP_PHI: {
84 pseudo_t phi;
85 FOR_EACH_PTR(insn->phi_list, phi) {
86 struct instruction *def;
87 if (phi == VOID)
88 continue;
89 def = phi->def;
90 hash += hashval(def->src1);
91 hash += hashval(def->bb);
92 } END_FOR_EACH_PTR(phi);
93 break;
96 case OP_PHISOURCE:
97 hash += hashval(insn->src1);
98 hash += hashval(insn->bb);
99 break;
101 default:
103 * Nothing to do, don't even bother hashing them,
104 * we're not going to try to CSE them
106 return;
108 hash += hash >> 16;
109 hash &= INSN_HASH_SIZE-1;
110 add_instruction(insn_hash_table + hash, insn);
113 static void clean_up_insns(struct entrypoint *ep)
115 struct basic_block *bb;
117 FOR_EACH_PTR(ep->bbs, bb) {
118 struct instruction *insn;
119 FOR_EACH_PTR(bb->insns, insn) {
120 clean_up_one_instruction(bb, insn);
121 } END_FOR_EACH_PTR(insn);
122 } END_FOR_EACH_PTR(bb);
125 extern void show_instruction(struct instruction *);
127 /* Compare two (sorted) phi-lists */
128 static int phi_list_compare(struct pseudo_list *l1, struct pseudo_list *l2)
130 pseudo_t phi1, phi2;
132 PREPARE_PTR_LIST(l1, phi1);
133 PREPARE_PTR_LIST(l2, phi2);
134 for (;;) {
135 int cmp;
137 while (phi1 == VOID)
138 NEXT_PTR_LIST(phi1);
139 while (phi2 == VOID)
140 NEXT_PTR_LIST(phi2);
142 if (!phi1)
143 return phi2 ? -1 : 0;
144 if (!phi2)
145 return phi1 ? 1 : 0;
146 cmp = phi_compare(phi1, phi2);
147 if (cmp)
148 return cmp;
149 NEXT_PTR_LIST(phi1);
150 NEXT_PTR_LIST(phi2);
152 /* Not reached, but we need to make the nesting come out right */
153 FINISH_PTR_LIST(phi2);
154 FINISH_PTR_LIST(phi1);
157 static int insn_compare(const void *_i1, const void *_i2)
159 const struct instruction *i1 = _i1;
160 const struct instruction *i2 = _i2;
162 if (i1->opcode != i2->opcode)
163 return i1->opcode < i2->opcode ? -1 : 1;
165 switch (i1->opcode) {
167 /* Binary arithmetic */
168 case OP_ADD: case OP_SUB:
169 case OP_MUL: case OP_DIV:
170 case OP_MOD: case OP_SHL:
171 case OP_SHR:
172 case OP_AND: case OP_OR:
174 /* Binary logical */
175 case OP_XOR: case OP_AND_BOOL:
176 case OP_OR_BOOL:
178 /* Binary comparison */
179 case OP_SET_EQ: case OP_SET_NE:
180 case OP_SET_LE: case OP_SET_GE:
181 case OP_SET_LT: case OP_SET_GT:
182 case OP_SET_B: case OP_SET_A:
183 case OP_SET_BE: case OP_SET_AE:
184 if (i1->src1 != i2->src1)
185 return i1->src1 < i2->src1 ? -1 : 1;
186 if (i1->src2 != i2->src2)
187 return i1->src2 < i2->src2 ? -1 : 1;
188 break;
190 /* Unary */
191 case OP_NOT: case OP_NEG:
192 if (i1->src1 != i2->src1)
193 return i1->src1 < i2->src1 ? -1 : 1;
194 break;
196 case OP_SETVAL:
197 if (i1->val != i2->val)
198 return i1->val < i2->val ? -1 : 1;
199 if (i1->symbol != i2->symbol)
200 return i1->symbol < i2->symbol ? -1 : 1;
201 break;
203 /* Other */
204 case OP_PHI:
205 return phi_list_compare(i1->phi_list, i2->phi_list);
207 case OP_PHISOURCE:
208 if (i1->src1 != i2->src1)
209 return i1->src1 < i2->src1 ? -1 : 1;
210 if (i1->bb != i2->bb)
211 return i1->bb < i2->bb ? -1 : 1;
212 if (!merge_phi_sources) {
213 if (i1 != i2)
214 return i1 < i2 ? -1 : 1;
216 break;
218 default:
219 warning(i1->bb->pos, "bad instruction on hash chain");
221 if (i1->size != i2->size)
222 return i1->size < i2->size ? -1 : 1;
223 return 0;
226 static void sort_instruction_list(struct instruction_list **list)
228 sort_list((struct ptr_list **)list , insn_compare);
231 static struct instruction * cse_one_instruction(struct instruction *insn, struct instruction *def)
233 convert_instruction_target(insn, def->target);
234 insn->opcode = OP_NOP;
235 insn->bb = NULL;
236 repeat_phase |= REPEAT_CSE;
237 return def;
241 * Does "bb1" dominate "bb2"?
243 static int bb_dominates(struct entrypoint *ep, struct basic_block *bb1, struct basic_block *bb2, unsigned long generation)
245 struct basic_block *parent;
247 /* Nothing dominates the entrypoint.. */
248 if (bb2 == ep->entry)
249 return 0;
250 FOR_EACH_PTR(bb2->parents, parent) {
251 if (parent == bb1)
252 continue;
253 if (parent->generation == generation)
254 continue;
255 parent->generation = generation;
256 if (!bb_dominates(ep, bb1, parent, generation))
257 return 0;
258 } END_FOR_EACH_PTR(parent);
259 return 1;
262 static inline void remove_instruction(struct instruction_list **list, struct instruction *insn, int count)
264 delete_ptr_list_entry((struct ptr_list **)list, insn, count);
267 static void add_instruction_to_end(struct instruction *insn, struct basic_block *bb)
269 struct instruction *br = delete_last_instruction(&bb->insns);
270 insn->bb = bb;
271 add_instruction(&bb->insns, insn);
272 add_instruction(&bb->insns, br);
275 static struct instruction * try_to_cse(struct entrypoint *ep, struct instruction *i1, struct instruction *i2)
277 struct basic_block *b1, *b2, *common;
280 * Ok, i1 and i2 are the same instruction, modulo "target".
281 * We should now see if we can combine them.
283 b1 = i1->bb;
284 b2 = i2->bb;
287 * Currently we only handle the uninteresting degenerate case where
288 * the CSE is inside one basic-block.
290 if (b1 == b2) {
291 struct instruction *insn;
292 FOR_EACH_PTR(b1->insns, insn) {
293 if (insn == i1)
294 return cse_one_instruction(i2, i1);
295 if (insn == i2)
296 return cse_one_instruction(i1, i2);
297 } END_FOR_EACH_PTR(insn);
298 warning(b1->pos, "Whaa? unable to find CSE instructions");
299 return i1;
301 if (bb_dominates(ep, b1, b2, ++bb_generation))
302 return cse_one_instruction(i2, i1);
304 if (bb_dominates(ep, b2, b1, ++bb_generation))
305 return cse_one_instruction(i1, i2);
307 /* No direct dominance - but we could try to find a common ancestor.. */
308 common = trivial_common_parent(b1, VOID, b2, VOID);
309 if (common) {
310 i1 = cse_one_instruction(i2, i1);
311 remove_instruction(&b1->insns, i1, 1);
312 add_instruction_to_end(i1, common);
315 return i1;
318 void cleanup_and_cse(struct entrypoint *ep)
320 int i;
322 simplify_memops(ep);
323 repeat:
324 repeat_phase = 0;
325 clean_up_insns(ep);
326 for (i = 0; i < INSN_HASH_SIZE; i++) {
327 struct instruction_list **list = insn_hash_table + i;
328 if (*list) {
329 if (instruction_list_size(*list) > 1) {
330 struct instruction *insn, *last;
332 sort_instruction_list(list);
334 last = NULL;
335 FOR_EACH_PTR(*list, insn) {
336 if (!insn->bb)
337 continue;
338 if (last) {
339 if (!insn_compare(last, insn))
340 insn = try_to_cse(ep, last, insn);
342 last = insn;
343 } END_FOR_EACH_PTR(insn);
345 free_ptr_list((struct ptr_list **)list);
349 if (repeat_phase & REPEAT_SYMBOL_CLEANUP)
350 simplify_memops(ep);
352 if (repeat_phase & REPEAT_CSE)
353 goto repeat;