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
16 #include "expression.h"
17 #include "linearize.h"
20 #define INSN_HASH_SIZE 256
21 static struct instruction_list
*insn_hash_table
[INSN_HASH_SIZE
];
25 static int phi_compare(pseudo_t phi1
, pseudo_t phi2
)
27 const struct instruction
*def1
= phi1
->def
;
28 const struct instruction
*def2
= phi2
->def
;
30 if (def1
->src1
!= def2
->src1
)
31 return def1
->src1
< def2
->src1
? -1 : 1;
32 if (def1
->bb
!= def2
->bb
)
33 return def1
->bb
< def2
->bb
? -1 : 1;
38 static void clean_up_one_instruction(struct basic_block
*bb
, struct instruction
*insn
)
44 assert(insn
->bb
== bb
);
45 repeat_phase
|= simplify_instruction(insn
);
46 hash
= (insn
->opcode
<< 3) + (insn
->size
>> 3);
47 switch (insn
->opcode
) {
49 hash
+= hashval(insn
->src3
);
52 /* Binary arithmetic */
53 case OP_ADD
: case OP_SUB
:
54 case OP_MULU
: case OP_MULS
:
55 case OP_DIVU
: case OP_DIVS
:
56 case OP_MODU
: case OP_MODS
:
58 case OP_LSR
: case OP_ASR
:
59 case OP_AND
: case OP_OR
:
62 case OP_XOR
: case OP_AND_BOOL
:
65 /* Binary comparison */
66 case OP_SET_EQ
: case OP_SET_NE
:
67 case OP_SET_LE
: case OP_SET_GE
:
68 case OP_SET_LT
: case OP_SET_GT
:
69 case OP_SET_B
: case OP_SET_A
:
70 case OP_SET_BE
: case OP_SET_AE
:
71 hash
+= hashval(insn
->src2
);
75 case OP_NOT
: case OP_NEG
:
76 hash
+= hashval(insn
->src1
);
80 hash
+= hashval(insn
->val
);
84 hash
+= hashval(insn
->symbol
);
91 * This is crap! Many "orig_types" are the
92 * same as far as casts go, we should generate
93 * some kind of "type hash" that is identical
96 hash
+= hashval(insn
->orig_type
);
97 hash
+= hashval(insn
->src
);
103 FOR_EACH_PTR(insn
->phi_list
, phi
) {
104 struct instruction
*def
;
105 if (phi
== VOID
|| !phi
->def
)
108 hash
+= hashval(def
->src1
);
109 hash
+= hashval(def
->bb
);
110 } END_FOR_EACH_PTR(phi
);
116 * Nothing to do, don't even bother hashing them,
117 * we're not going to try to CSE them
122 hash
&= INSN_HASH_SIZE
-1;
123 add_instruction(insn_hash_table
+ hash
, insn
);
126 static void clean_up_insns(struct entrypoint
*ep
)
128 struct basic_block
*bb
;
130 FOR_EACH_PTR(ep
->bbs
, bb
) {
131 struct instruction
*insn
;
132 FOR_EACH_PTR(bb
->insns
, insn
) {
133 clean_up_one_instruction(bb
, insn
);
134 } END_FOR_EACH_PTR(insn
);
135 } END_FOR_EACH_PTR(bb
);
138 /* Compare two (sorted) phi-lists */
139 static int phi_list_compare(struct pseudo_list
*l1
, struct pseudo_list
*l2
)
143 PREPARE_PTR_LIST(l1
, phi1
);
144 PREPARE_PTR_LIST(l2
, phi2
);
148 while (phi1
&& (phi1
== VOID
|| !phi1
->def
))
150 while (phi2
&& (phi2
== VOID
|| !phi2
->def
))
154 return phi2
? -1 : 0;
157 cmp
= phi_compare(phi1
, phi2
);
163 /* Not reached, but we need to make the nesting come out right */
164 FINISH_PTR_LIST(phi2
);
165 FINISH_PTR_LIST(phi1
);
168 static int insn_compare(const void *_i1
, const void *_i2
)
170 const struct instruction
*i1
= _i1
;
171 const struct instruction
*i2
= _i2
;
173 if (i1
->opcode
!= i2
->opcode
)
174 return i1
->opcode
< i2
->opcode
? -1 : 1;
176 switch (i1
->opcode
) {
178 if (i1
->src3
!= i2
->src3
)
179 return i1
->src3
< i2
->src3
? -1 : 1;
180 /* Fall-through to binops */
182 /* Binary arithmetic */
183 case OP_ADD
: case OP_SUB
:
184 case OP_MULU
: case OP_MULS
:
185 case OP_DIVU
: case OP_DIVS
:
186 case OP_MODU
: case OP_MODS
:
188 case OP_LSR
: case OP_ASR
:
189 case OP_AND
: case OP_OR
:
192 case OP_XOR
: case OP_AND_BOOL
:
195 /* Binary comparison */
196 case OP_SET_EQ
: case OP_SET_NE
:
197 case OP_SET_LE
: case OP_SET_GE
:
198 case OP_SET_LT
: case OP_SET_GT
:
199 case OP_SET_B
: case OP_SET_A
:
200 case OP_SET_BE
: case OP_SET_AE
:
201 if (i1
->src2
!= i2
->src2
)
202 return i1
->src2
< i2
->src2
? -1 : 1;
203 /* Fall through to unops */
206 case OP_NOT
: case OP_NEG
:
207 if (i1
->src1
!= i2
->src1
)
208 return i1
->src1
< i2
->src1
? -1 : 1;
212 if (i1
->symbol
!= i2
->symbol
)
213 return i1
->symbol
< i2
->symbol
? -1 : 1;
217 if (i1
->val
!= i2
->val
)
218 return i1
->val
< i2
->val
? -1 : 1;
223 return phi_list_compare(i1
->phi_list
, i2
->phi_list
);
229 * This is crap! See the comments on hashing.
231 if (i1
->orig_type
!= i2
->orig_type
)
232 return i1
->orig_type
< i2
->orig_type
? -1 : 1;
233 if (i1
->src
!= i2
->src
)
234 return i1
->src
< i2
->src
? -1 : 1;
238 warning(i1
->pos
, "bad instruction on hash chain");
240 if (i1
->size
!= i2
->size
)
241 return i1
->size
< i2
->size
? -1 : 1;
245 static void sort_instruction_list(struct instruction_list
**list
)
247 sort_list((struct ptr_list
**)list
, insn_compare
);
250 static struct instruction
* cse_one_instruction(struct instruction
*insn
, struct instruction
*def
)
252 convert_instruction_target(insn
, def
->target
);
254 if (insn
->opcode
== OP_PHI
) {
255 /* Remove the instruction from PHI users */
257 FOR_EACH_PTR(insn
->phi_list
, phi
) {
258 struct pseudo_user
*pu
;
259 FOR_EACH_PTR(phi
->users
, pu
) {
260 if (pu
->insn
== insn
)
261 DELETE_CURRENT_PTR(pu
);
262 } END_FOR_EACH_PTR(pu
);
263 } END_FOR_EACH_PTR(phi
);
266 insn
->opcode
= OP_NOP
;
268 repeat_phase
|= REPEAT_CSE
;
273 * Does "bb1" dominate "bb2"?
275 static int bb_dominates(struct entrypoint
*ep
, struct basic_block
*bb1
, struct basic_block
*bb2
, unsigned long generation
)
277 struct basic_block
*parent
;
279 /* Nothing dominates the entrypoint.. */
280 if (bb2
== ep
->entry
->bb
)
282 FOR_EACH_PTR(bb2
->parents
, parent
) {
285 if (parent
->generation
== generation
)
287 parent
->generation
= generation
;
288 if (!bb_dominates(ep
, bb1
, parent
, generation
))
290 } END_FOR_EACH_PTR(parent
);
294 static struct basic_block
*trivial_common_parent(struct basic_block
*bb1
, struct basic_block
*bb2
)
296 struct basic_block
*parent
;
298 if (bb_list_size(bb1
->parents
) != 1)
300 parent
= first_basic_block(bb1
->parents
);
301 if (bb_list_size(bb2
->parents
) != 1)
303 if (first_basic_block(bb2
->parents
) != parent
)
308 static inline void remove_instruction(struct instruction_list
**list
, struct instruction
*insn
, int count
)
310 delete_ptr_list_entry((struct ptr_list
**)list
, insn
, count
);
313 static void add_instruction_to_end(struct instruction
*insn
, struct basic_block
*bb
)
315 struct instruction
*br
= delete_last_instruction(&bb
->insns
);
317 add_instruction(&bb
->insns
, insn
);
318 add_instruction(&bb
->insns
, br
);
321 static struct instruction
* try_to_cse(struct entrypoint
*ep
, struct instruction
*i1
, struct instruction
*i2
)
323 struct basic_block
*b1
, *b2
, *common
;
326 * OK, i1 and i2 are the same instruction, modulo "target".
327 * We should now see if we can combine them.
333 * Currently we only handle the uninteresting degenerate case where
334 * the CSE is inside one basic-block.
337 struct instruction
*insn
;
338 FOR_EACH_PTR(b1
->insns
, insn
) {
340 return cse_one_instruction(i2
, i1
);
342 return cse_one_instruction(i1
, i2
);
343 } END_FOR_EACH_PTR(insn
);
344 warning(b1
->pos
, "Whaa? unable to find CSE instructions");
347 if (bb_dominates(ep
, b1
, b2
, ++bb_generation
))
348 return cse_one_instruction(i2
, i1
);
350 if (bb_dominates(ep
, b2
, b1
, ++bb_generation
))
351 return cse_one_instruction(i1
, i2
);
353 /* No direct dominance - but we could try to find a common ancestor.. */
354 common
= trivial_common_parent(b1
, b2
);
356 i1
= cse_one_instruction(i2
, i1
);
357 remove_instruction(&b1
->insns
, i1
, 1);
358 add_instruction_to_end(i1
, common
);
364 void cleanup_and_cse(struct entrypoint
*ep
)
372 for (i
= 0; i
< INSN_HASH_SIZE
; i
++) {
373 struct instruction_list
**list
= insn_hash_table
+ i
;
375 if (instruction_list_size(*list
) > 1) {
376 struct instruction
*insn
, *last
;
378 sort_instruction_list(list
);
381 FOR_EACH_PTR(*list
, insn
) {
385 if (!insn_compare(last
, insn
))
386 insn
= try_to_cse(ep
, last
, insn
);
389 } END_FOR_EACH_PTR(insn
);
391 free_ptr_list((struct ptr_list
**)list
);
395 if (repeat_phase
& REPEAT_SYMBOL_CLEANUP
)
398 if (repeat_phase
& REPEAT_CSE
)