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 "flowgraph.h"
18 #include "linearize.h"
22 #define INSN_HASH_SIZE 256
23 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 void cse_collect(struct instruction
*insn
)
42 hash
= (insn
->opcode
<< 3) + (insn
->size
>> 3);
43 switch (insn
->opcode
) {
45 hash
+= hashval(insn
->src3
);
48 /* Binary arithmetic */
49 case OP_ADD
: case OP_SUB
:
51 case OP_DIVU
: case OP_DIVS
:
52 case OP_MODU
: case OP_MODS
:
54 case OP_LSR
: case OP_ASR
:
55 case OP_AND
: case OP_OR
:
60 /* Binary comparison */
61 case OP_SET_EQ
: case OP_SET_NE
:
62 case OP_SET_LE
: case OP_SET_GE
:
63 case OP_SET_LT
: case OP_SET_GT
:
64 case OP_SET_B
: case OP_SET_A
:
65 case OP_SET_BE
: case OP_SET_AE
:
67 /* floating-point arithmetic & comparison */
68 case OP_FPCMP
... OP_FPCMP_END
:
73 hash
+= hashval(insn
->src2
);
77 case OP_NOT
: case OP_NEG
:
80 hash
+= hashval(insn
->src1
);
84 hash
+= hashval(insn
->bb_true
);
88 hash
+= hashval(insn
->val
);
92 hash
+= hashval(insn
->fvalue
);
95 case OP_SEXT
: case OP_ZEXT
:
98 case OP_UTPTR
: case OP_PTRTU
:
99 if (!insn
->orig_type
|| insn
->orig_type
->bit_size
< 0)
101 hash
+= hashval(insn
->src
);
103 // Note: see corresponding line in insn_compare()
104 hash
+= hashval(insn
->orig_type
->bit_size
);
110 FOR_EACH_PTR(insn
->phi_list
, phi
) {
111 struct instruction
*def
;
112 if (phi
== VOID
|| !phi
->def
)
115 hash
+= hashval(def
->src1
);
116 hash
+= hashval(def
->bb
);
117 } END_FOR_EACH_PTR(phi
);
123 * Nothing to do, don't even bother hashing them,
124 * we're not going to try to CSE them
129 hash
&= INSN_HASH_SIZE
-1;
130 add_instruction(insn_hash_table
+ hash
, insn
);
133 /* Compare two (sorted) phi-lists */
134 static int phi_list_compare(struct pseudo_list
*l1
, struct pseudo_list
*l2
)
138 PREPARE_PTR_LIST(l1
, phi1
);
139 PREPARE_PTR_LIST(l2
, phi2
);
143 while (phi1
&& (phi1
== VOID
|| !phi1
->def
))
145 while (phi2
&& (phi2
== VOID
|| !phi2
->def
))
149 return phi2
? -1 : 0;
152 cmp
= phi_compare(phi1
, phi2
);
158 /* Not reached, but we need to make the nesting come out right */
159 FINISH_PTR_LIST(phi2
);
160 FINISH_PTR_LIST(phi1
);
163 static int insn_compare(const void *_i1
, const void *_i2
)
165 const struct instruction
*i1
= _i1
;
166 const struct instruction
*i2
= _i2
;
170 if (i1
->opcode
!= i2
->opcode
)
171 return i1
->opcode
< i2
->opcode
? -1 : 1;
173 switch (i1
->opcode
) {
175 /* commutative binop */
178 case OP_AND
: case OP_OR
:
180 case OP_SET_EQ
: case OP_SET_NE
:
181 if (i1
->src1
== i2
->src2
&& i1
->src2
== i2
->src1
)
186 if (i1
->src3
!= i2
->src3
)
187 return i1
->src3
< i2
->src3
? -1 : 1;
188 /* Fall-through to binops */
190 /* Binary arithmetic */
192 case OP_DIVU
: case OP_DIVS
:
193 case OP_MODU
: case OP_MODS
:
195 case OP_LSR
: case OP_ASR
:
197 /* Binary comparison */
198 case OP_SET_LE
: case OP_SET_GE
:
199 case OP_SET_LT
: case OP_SET_GT
:
200 case OP_SET_B
: case OP_SET_A
:
201 case OP_SET_BE
: case OP_SET_AE
:
203 /* floating-point arithmetic */
204 case OP_FPCMP
... OP_FPCMP_END
:
210 if (i1
->src2
!= i2
->src2
)
211 return i1
->src2
< i2
->src2
? -1 : 1;
212 /* Fall through to unops */
215 case OP_NOT
: case OP_NEG
:
218 if (i1
->src1
!= i2
->src1
)
219 return i1
->src1
< i2
->src1
? -1 : 1;
223 if (i1
->bb_true
!= i2
->bb_true
)
224 return i1
->bb_true
< i2
->bb_true
? -1 : 1;
228 if (i1
->val
!= i2
->val
)
229 return i1
->val
< i2
->val
? -1 : 1;
233 diff
= memcmp(&i1
->fvalue
, &i2
->fvalue
, sizeof(i1
->fvalue
));
240 return phi_list_compare(i1
->phi_list
, i2
->phi_list
);
242 case OP_SEXT
: case OP_ZEXT
:
245 case OP_UTPTR
: case OP_PTRTU
:
246 if (i1
->src
!= i2
->src
)
247 return i1
->src
< i2
->src
? -1 : 1;
249 // Note: if it can be guaranted that identical ->src
250 // implies identical orig_type->bit_size, then this
251 // test and the hashing of the original size in
252 // cse_collect() are not needed.
253 // It must be generaly true but it isn't guaranted (yet).
254 size1
= i1
->orig_type
->bit_size
;
255 size2
= i2
->orig_type
->bit_size
;
257 return size1
< size2
? -1 : 1;
261 warning(i1
->pos
, "bad instruction on hash chain");
263 if (i1
->size
!= i2
->size
)
264 return i1
->size
< i2
->size
? -1 : 1;
268 static void sort_instruction_list(struct instruction_list
**list
)
270 sort_list((struct ptr_list
**)list
, insn_compare
);
273 static struct instruction
* cse_one_instruction(struct instruction
*insn
, struct instruction
*def
)
275 convert_instruction_target(insn
, def
->target
);
277 kill_instruction(insn
);
278 repeat_phase
|= REPEAT_CSE
;
282 static struct basic_block
*trivial_common_parent(struct basic_block
*bb1
, struct basic_block
*bb2
)
284 struct basic_block
*parent
;
286 if (bb_list_size(bb1
->parents
) != 1)
288 parent
= first_basic_block(bb1
->parents
);
289 if (bb_list_size(bb2
->parents
) != 1)
291 if (first_basic_block(bb2
->parents
) != parent
)
296 static inline void remove_instruction(struct instruction_list
**list
, struct instruction
*insn
, int count
)
298 delete_ptr_list_entry((struct ptr_list
**)list
, insn
, count
);
301 static void add_instruction_to_end(struct instruction
*insn
, struct basic_block
*bb
)
303 struct instruction
*br
= delete_last_instruction(&bb
->insns
);
305 add_instruction(&bb
->insns
, insn
);
306 add_instruction(&bb
->insns
, br
);
309 static struct instruction
* try_to_cse(struct entrypoint
*ep
, struct instruction
*i1
, struct instruction
*i2
)
311 struct basic_block
*b1
, *b2
, *common
;
314 * OK, i1 and i2 are the same instruction, modulo "target".
315 * We should now see if we can combine them.
321 * Currently we only handle the uninteresting degenerate case where
322 * the CSE is inside one basic-block.
325 struct instruction
*insn
;
326 FOR_EACH_PTR(b1
->insns
, insn
) {
328 return cse_one_instruction(i2
, i1
);
330 return cse_one_instruction(i1
, i2
);
331 } END_FOR_EACH_PTR(insn
);
332 warning(b1
->pos
, "Whaa? unable to find CSE instructions");
335 if (domtree_dominates(b1
, b2
))
336 return cse_one_instruction(i2
, i1
);
338 if (domtree_dominates(b2
, b1
))
339 return cse_one_instruction(i1
, i2
);
341 /* No direct dominance - but we could try to find a common ancestor.. */
342 common
= trivial_common_parent(b1
, b2
);
344 i1
= cse_one_instruction(i2
, i1
);
345 remove_instruction(&b1
->insns
, i1
, 1);
346 add_instruction_to_end(i1
, common
);
354 void cse_eliminate(struct entrypoint
*ep
)
358 for (i
= 0; i
< INSN_HASH_SIZE
; i
++) {
359 struct instruction_list
**list
= insn_hash_table
+ i
;
361 if (instruction_list_size(*list
) > 1) {
362 struct instruction
*insn
, *last
;
364 sort_instruction_list(list
);
367 FOR_EACH_PTR(*list
, insn
) {
371 if (!insn_compare(last
, insn
))
372 insn
= try_to_cse(ep
, last
, insn
);
375 } END_FOR_EACH_PTR(insn
);