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 65536
21 static struct instruction_list
*insn_hash_table
[INSN_HASH_SIZE
];
23 #define hashval(x) ((unsigned long)(x))
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;
40 static void clean_up_one_instruction(struct basic_block
*bb
, struct instruction
*insn
)
46 assert(insn
->bb
== bb
);
47 repeat_phase
|= simplify_instruction(insn
);
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
: case OP_SEL
:
56 case OP_AND
: case OP_OR
:
59 case OP_XOR
: case OP_AND_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
);
73 case OP_NOT
: case OP_NEG
:
74 hash
+= hashval(insn
->src1
);
78 hash
+= hashval(insn
->val
);
79 hash
+= hashval(insn
->symbol
);
85 FOR_EACH_PTR(insn
->phi_list
, phi
) {
86 struct instruction
*def
;
90 hash
+= hashval(def
->src1
);
91 hash
+= hashval(def
->bb
);
92 } END_FOR_EACH_PTR(phi
);
97 hash
+= hashval(insn
->src1
);
98 hash
+= hashval(insn
->bb
);
103 * Nothing to do, don't even bother hashing them,
104 * we're not going to try to CSE them
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
)
132 PREPARE_PTR_LIST(l1
, phi1
);
133 PREPARE_PTR_LIST(l2
, phi2
);
143 return phi2
? -1 : 0;
146 cmp
= phi_compare(phi1
, 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
: case OP_SEL
:
172 case OP_AND
: case OP_OR
:
175 case OP_XOR
: case OP_AND_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;
191 case OP_NOT
: case OP_NEG
:
192 if (i1
->src1
!= i2
->src1
)
193 return i1
->src1
< i2
->src1
? -1 : 1;
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;
205 return phi_list_compare(i1
->phi_list
, i2
->phi_list
);
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;
215 warning(i1
->bb
->pos
, "bad instruction on hash chain");
220 static void sort_instruction_list(struct instruction_list
**list
)
222 sort_list((struct ptr_list
**)list
, insn_compare
);
225 static struct instruction
* cse_one_instruction(struct instruction
*insn
, struct instruction
*def
)
227 convert_instruction_target(insn
, def
->target
);
228 insn
->opcode
= OP_NOP
;
230 repeat_phase
|= REPEAT_CSE
;
235 * Does "bb1" dominate "bb2"?
237 static int bb_dominates(struct entrypoint
*ep
, struct basic_block
*bb1
, struct basic_block
*bb2
, unsigned long generation
)
239 struct basic_block
*parent
;
241 /* Nothing dominates the entrypoint.. */
242 if (bb2
== ep
->entry
)
244 FOR_EACH_PTR(bb2
->parents
, parent
) {
247 if (parent
->generation
== generation
)
249 parent
->generation
= generation
;
250 if (!bb_dominates(ep
, bb1
, parent
, generation
))
252 } END_FOR_EACH_PTR(parent
);
256 static struct instruction
* try_to_cse(struct entrypoint
*ep
, struct instruction
*i1
, struct instruction
*i2
)
258 struct basic_block
*b1
, *b2
;
261 * Ok, i1 and i2 are the same instruction, modulo "target".
262 * We should now see if we can combine them.
268 * Currently we only handle the uninteresting degenerate case where
269 * the CSE is inside one basic-block.
272 struct instruction
*insn
;
273 FOR_EACH_PTR(b1
->insns
, insn
) {
275 return cse_one_instruction(i2
, i1
);
277 return cse_one_instruction(i1
, i2
);
278 } END_FOR_EACH_PTR(insn
);
279 warning(b1
->pos
, "Whaa? unable to find CSE instructions");
282 if (bb_dominates(ep
, b1
, b2
, ++bb_generation
))
283 return cse_one_instruction(i2
, i1
);
285 if (bb_dominates(ep
, b2
, b1
, ++bb_generation
))
286 return cse_one_instruction(i1
, i2
);
288 /* No direct dominance - but we could try to find a common ancestor.. */
292 void cleanup_and_cse(struct entrypoint
*ep
)
299 for (i
= 0; i
< INSN_HASH_SIZE
; i
++) {
300 struct instruction_list
**list
= insn_hash_table
+ i
;
302 if (instruction_list_size(*list
) > 1) {
303 struct instruction
*insn
, *last
;
305 sort_instruction_list(list
);
308 FOR_EACH_PTR(*list
, insn
) {
312 if (!insn_compare(last
, insn
))
313 insn
= try_to_cse(ep
, last
, insn
);
316 } END_FOR_EACH_PTR(insn
);
318 free_ptr_list((struct ptr_list
**)list
);
322 if (repeat_phase
& REPEAT_SYMBOL_CLEANUP
)
323 simplify_symbol_usage(ep
);
325 if (repeat_phase
& REPEAT_CSE
)