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
15 #include "expression.h"
16 #include "linearize.h"
19 #define INSN_HASH_SIZE 65536
20 static struct instruction_list
*insn_hash_table
[INSN_HASH_SIZE
];
22 #define hashval(x) ((unsigned long)(x))
24 static int phi_compare(const void *_phi1
, const void *_phi2
)
26 const struct phi
*phi1
= _phi1
;
27 const struct phi
*phi2
= _phi2
;
29 if (phi1
->pseudo
!= phi2
->pseudo
)
30 return phi1
->pseudo
< phi2
->pseudo
? -1 : 1;
31 if (phi1
->source
!= phi2
->source
)
32 return phi1
->source
< phi2
->source
? -1 : 1;
36 static void sort_phi_list(struct phi_list
**list
)
38 sort_list((struct ptr_list
**)list
, phi_compare
);
41 static unsigned long clean_up_phi(struct instruction
*insn
)
43 struct phi
*phi
, *last
;
44 unsigned long hash
= 0;
46 sort_phi_list(&insn
->phi_list
);
49 FOR_EACH_PTR(insn
->phi_list
, phi
) {
51 if (last
->pseudo
== phi
->pseudo
&&
52 last
->source
== phi
->source
) {
53 DELETE_CURRENT_PTR(phi
);
58 hash
+= hashval(phi
->pseudo
);
59 hash
+= hashval(phi
->source
);
60 } END_FOR_EACH_PTR(phi
);
64 static void clean_up_one_instruction(struct basic_block
*bb
, struct instruction
*insn
)
69 warning(bb
->pos
, "instruction with bad bb");
71 switch (insn
->opcode
) {
73 /* Binary arithmetic */
74 case OP_ADD
: case OP_SUB
:
75 case OP_MUL
: case OP_DIV
:
76 case OP_MOD
: case OP_SHL
:
77 case OP_SHR
: case OP_SEL
:
78 case OP_AND
: case OP_OR
:
81 case OP_XOR
: case OP_AND_BOOL
:
84 /* Binary comparison */
85 case OP_SET_EQ
: case OP_SET_NE
:
86 case OP_SET_LE
: case OP_SET_GE
:
87 case OP_SET_LT
: case OP_SET_GT
:
88 case OP_SET_B
: case OP_SET_A
:
89 case OP_SET_BE
: case OP_SET_AE
:
90 hash
+= hashval(insn
->src1
);
91 hash
+= hashval(insn
->src2
);
95 case OP_NOT
: case OP_NEG
:
96 hash
+= hashval(insn
->src1
);
100 hash
+= hashval(insn
->val
);
101 hash
+= hashval(insn
->symbol
);
106 hash
+= clean_up_phi(insn
);
111 * Nothing to do, don't even bother hashing them,
112 * we're not going to try to CSE them
117 hash
&= INSN_HASH_SIZE
-1;
118 add_instruction(insn_hash_table
+ hash
, insn
);
121 static void clean_up_insns(struct entrypoint
*ep
)
123 struct basic_block
*bb
;
125 FOR_EACH_PTR(ep
->bbs
, bb
) {
126 struct instruction
*insn
;
127 FOR_EACH_PTR(bb
->insns
, insn
) {
128 clean_up_one_instruction(bb
, insn
);
129 } END_FOR_EACH_PTR(insn
);
130 } END_FOR_EACH_PTR(bb
);
133 extern void show_instruction(struct instruction
*);
135 /* Compare two (sorted) phi-lists */
136 static int phi_list_compare(struct phi_list
*l1
, struct phi_list
*l2
)
138 struct phi
*phi1
, *phi2
;
140 PREPARE_PTR_LIST(l1
, phi1
);
141 PREPARE_PTR_LIST(l2
, phi2
);
146 return phi2
? -1 : 0;
149 cmp
= phi_compare(phi1
, phi2
);
155 /* Not reached, but we need to make the nesting come out right */
156 FINISH_PTR_LIST(phi2
);
157 FINISH_PTR_LIST(phi1
);
160 static int insn_compare(const void *_i1
, const void *_i2
)
162 const struct instruction
*i1
= _i1
;
163 const struct instruction
*i2
= _i2
;
165 if (i1
->opcode
!= i2
->opcode
)
166 return i1
->opcode
< i2
->opcode
? -1 : 1;
168 switch (i1
->opcode
) {
170 /* Binary arithmetic */
171 case OP_ADD
: case OP_SUB
:
172 case OP_MUL
: case OP_DIV
:
173 case OP_MOD
: case OP_SHL
:
174 case OP_SHR
: case OP_SEL
:
175 case OP_AND
: case OP_OR
:
178 case OP_XOR
: case OP_AND_BOOL
:
181 /* Binary comparison */
182 case OP_SET_EQ
: case OP_SET_NE
:
183 case OP_SET_LE
: case OP_SET_GE
:
184 case OP_SET_LT
: case OP_SET_GT
:
185 case OP_SET_B
: case OP_SET_A
:
186 case OP_SET_BE
: case OP_SET_AE
:
187 if (i1
->src1
!= i2
->src1
)
188 return i1
->src1
< i2
->src1
? -1 : 1;
189 if (i1
->src2
!= i2
->src2
)
190 return i1
->src2
< i2
->src2
? -1 : 1;
194 case OP_NOT
: case OP_NEG
:
195 if (i1
->src1
!= i2
->src1
)
196 return i1
->src1
< i2
->src1
? -1 : 1;
200 if (i1
->val
!= i2
->val
)
201 return i1
->val
< i2
->val
? -1 : 1;
202 if (i1
->symbol
!= i2
->symbol
)
203 return i1
->symbol
< i2
->symbol
? -1 : 1;
208 return phi_list_compare(i1
->phi_list
, i2
->phi_list
);
211 warning(i1
->bb
->pos
, "bad instruction on hash chain");
216 static void sort_instruction_list(struct instruction_list
**list
)
218 sort_list((struct ptr_list
**)list
, insn_compare
);
221 static struct instruction
* cse_one_instruction(struct instruction
*insn
, struct instruction
*def
)
223 /* We re-use the "convert_load_insn()" function. Does the same thing */
224 convert_load_insn(insn
, def
->target
);
228 static struct instruction
* try_to_cse(struct instruction
*i1
, struct instruction
*i2
)
230 struct basic_block
*b1
, *b2
;
233 * Ok, i1 and i2 are the same instruction, modulo "target".
234 * We should now see if we can combine them.
240 * Currently we only handle the uninteresting degenerate case where
241 * the CSE is inside one basic-block.
244 struct instruction
*insn
;
245 FOR_EACH_PTR(b1
->insns
, insn
) {
247 return cse_one_instruction(i2
, i1
);
249 return cse_one_instruction(i1
, i2
);
250 } END_FOR_EACH_PTR(insn
);
251 warning(b1
->pos
, "Whaa? unable to find CSE instructions");
256 void cleanup_and_cse(struct entrypoint
*ep
)
263 for (i
= 0; i
< INSN_HASH_SIZE
; i
++) {
264 struct instruction_list
**list
= insn_hash_table
+ i
;
266 if (instruction_list_size(*list
) > 1) {
267 struct instruction
*insn
, *last
;
269 sort_instruction_list(list
);
272 FOR_EACH_PTR(*list
, insn
) {
274 if (!insn_compare(last
, insn
)) {
275 struct instruction
*def
= try_to_cse(last
, insn
);
283 } END_FOR_EACH_PTR(insn
);
285 free_ptr_list((struct ptr_list
**)list
);