xref: /illumos-gate/usr/src/tools/smatch/src/cse.c (revision 1f5207b7)
1*1f5207b7SJohn Levon /*
2*1f5207b7SJohn Levon  * CSE - walk the linearized instruction flow, and
3*1f5207b7SJohn Levon  * see if we can simplify it and apply CSE on it.
4*1f5207b7SJohn Levon  *
5*1f5207b7SJohn Levon  * Copyright (C) 2004 Linus Torvalds
6*1f5207b7SJohn Levon  */
7*1f5207b7SJohn Levon 
8*1f5207b7SJohn Levon #include <string.h>
9*1f5207b7SJohn Levon #include <stdarg.h>
10*1f5207b7SJohn Levon #include <stdlib.h>
11*1f5207b7SJohn Levon #include <stdio.h>
12*1f5207b7SJohn Levon #include <stddef.h>
13*1f5207b7SJohn Levon #include <assert.h>
14*1f5207b7SJohn Levon 
15*1f5207b7SJohn Levon #include "parse.h"
16*1f5207b7SJohn Levon #include "expression.h"
17*1f5207b7SJohn Levon #include "linearize.h"
18*1f5207b7SJohn Levon #include "flow.h"
19*1f5207b7SJohn Levon 
20*1f5207b7SJohn Levon #define INSN_HASH_SIZE 256
21*1f5207b7SJohn Levon static struct instruction_list *insn_hash_table[INSN_HASH_SIZE];
22*1f5207b7SJohn Levon 
23*1f5207b7SJohn Levon int repeat_phase;
24*1f5207b7SJohn Levon 
25*1f5207b7SJohn Levon static int phi_compare(pseudo_t phi1, pseudo_t phi2)
26*1f5207b7SJohn Levon {
27*1f5207b7SJohn Levon 	const struct instruction *def1 = phi1->def;
28*1f5207b7SJohn Levon 	const struct instruction *def2 = phi2->def;
29*1f5207b7SJohn Levon 
30*1f5207b7SJohn Levon 	if (def1->src1 != def2->src1)
31*1f5207b7SJohn Levon 		return def1->src1 < def2->src1 ? -1 : 1;
32*1f5207b7SJohn Levon 	if (def1->bb != def2->bb)
33*1f5207b7SJohn Levon 		return def1->bb < def2->bb ? -1 : 1;
34*1f5207b7SJohn Levon 	return 0;
35*1f5207b7SJohn Levon }
36*1f5207b7SJohn Levon 
37*1f5207b7SJohn Levon 
38*1f5207b7SJohn Levon static void clean_up_one_instruction(struct basic_block *bb, struct instruction *insn)
39*1f5207b7SJohn Levon {
40*1f5207b7SJohn Levon 	unsigned long hash;
41*1f5207b7SJohn Levon 
42*1f5207b7SJohn Levon 	if (!insn->bb)
43*1f5207b7SJohn Levon 		return;
44*1f5207b7SJohn Levon 	assert(insn->bb == bb);
45*1f5207b7SJohn Levon 	repeat_phase |= simplify_instruction(insn);
46*1f5207b7SJohn Levon 	if (!insn->bb)
47*1f5207b7SJohn Levon 		return;
48*1f5207b7SJohn Levon 	hash = (insn->opcode << 3) + (insn->size >> 3);
49*1f5207b7SJohn Levon 	switch (insn->opcode) {
50*1f5207b7SJohn Levon 	case OP_SEL:
51*1f5207b7SJohn Levon 		hash += hashval(insn->src3);
52*1f5207b7SJohn Levon 		/* Fall through */
53*1f5207b7SJohn Levon 
54*1f5207b7SJohn Levon 	/* Binary arithmetic */
55*1f5207b7SJohn Levon 	case OP_ADD: case OP_SUB:
56*1f5207b7SJohn Levon 	case OP_MULU: case OP_MULS:
57*1f5207b7SJohn Levon 	case OP_DIVU: case OP_DIVS:
58*1f5207b7SJohn Levon 	case OP_MODU: case OP_MODS:
59*1f5207b7SJohn Levon 	case OP_SHL:
60*1f5207b7SJohn Levon 	case OP_LSR: case OP_ASR:
61*1f5207b7SJohn Levon 	case OP_AND: case OP_OR:
62*1f5207b7SJohn Levon 
63*1f5207b7SJohn Levon 	/* Binary logical */
64*1f5207b7SJohn Levon 	case OP_XOR: case OP_AND_BOOL:
65*1f5207b7SJohn Levon 	case OP_OR_BOOL:
66*1f5207b7SJohn Levon 
67*1f5207b7SJohn Levon 	/* Binary comparison */
68*1f5207b7SJohn Levon 	case OP_SET_EQ: case OP_SET_NE:
69*1f5207b7SJohn Levon 	case OP_SET_LE: case OP_SET_GE:
70*1f5207b7SJohn Levon 	case OP_SET_LT: case OP_SET_GT:
71*1f5207b7SJohn Levon 	case OP_SET_B:  case OP_SET_A:
72*1f5207b7SJohn Levon 	case OP_SET_BE: case OP_SET_AE:
73*1f5207b7SJohn Levon 		hash += hashval(insn->src2);
74*1f5207b7SJohn Levon 		/* Fall through */
75*1f5207b7SJohn Levon 
76*1f5207b7SJohn Levon 	/* Unary */
77*1f5207b7SJohn Levon 	case OP_NOT: case OP_NEG:
78*1f5207b7SJohn Levon 		hash += hashval(insn->src1);
79*1f5207b7SJohn Levon 		break;
80*1f5207b7SJohn Levon 
81*1f5207b7SJohn Levon 	case OP_SETVAL:
82*1f5207b7SJohn Levon 		hash += hashval(insn->val);
83*1f5207b7SJohn Levon 		break;
84*1f5207b7SJohn Levon 
85*1f5207b7SJohn Levon 	case OP_SYMADDR:
86*1f5207b7SJohn Levon 		hash += hashval(insn->symbol);
87*1f5207b7SJohn Levon 		break;
88*1f5207b7SJohn Levon 
89*1f5207b7SJohn Levon 	case OP_CAST:
90*1f5207b7SJohn Levon 	case OP_SCAST:
91*1f5207b7SJohn Levon 	case OP_PTRCAST:
92*1f5207b7SJohn Levon 		/*
93*1f5207b7SJohn Levon 		 * This is crap! Many "orig_types" are the
94*1f5207b7SJohn Levon 		 * same as far as casts go, we should generate
95*1f5207b7SJohn Levon 		 * some kind of "type hash" that is identical
96*1f5207b7SJohn Levon 		 * for identical casts
97*1f5207b7SJohn Levon 		 */
98*1f5207b7SJohn Levon 		hash += hashval(insn->orig_type);
99*1f5207b7SJohn Levon 		hash += hashval(insn->src);
100*1f5207b7SJohn Levon 		break;
101*1f5207b7SJohn Levon 
102*1f5207b7SJohn Levon 	/* Other */
103*1f5207b7SJohn Levon 	case OP_PHI: {
104*1f5207b7SJohn Levon 		pseudo_t phi;
105*1f5207b7SJohn Levon 		FOR_EACH_PTR(insn->phi_list, phi) {
106*1f5207b7SJohn Levon 			struct instruction *def;
107*1f5207b7SJohn Levon 			if (phi == VOID || !phi->def)
108*1f5207b7SJohn Levon 				continue;
109*1f5207b7SJohn Levon 			def = phi->def;
110*1f5207b7SJohn Levon 			hash += hashval(def->src1);
111*1f5207b7SJohn Levon 			hash += hashval(def->bb);
112*1f5207b7SJohn Levon 		} END_FOR_EACH_PTR(phi);
113*1f5207b7SJohn Levon 		break;
114*1f5207b7SJohn Levon 	}
115*1f5207b7SJohn Levon 
116*1f5207b7SJohn Levon 	default:
117*1f5207b7SJohn Levon 		/*
118*1f5207b7SJohn Levon 		 * Nothing to do, don't even bother hashing them,
119*1f5207b7SJohn Levon 		 * we're not going to try to CSE them
120*1f5207b7SJohn Levon 		 */
121*1f5207b7SJohn Levon 		return;
122*1f5207b7SJohn Levon 	}
123*1f5207b7SJohn Levon 	hash += hash >> 16;
124*1f5207b7SJohn Levon 	hash &= INSN_HASH_SIZE-1;
125*1f5207b7SJohn Levon 	add_instruction(insn_hash_table + hash, insn);
126*1f5207b7SJohn Levon }
127*1f5207b7SJohn Levon 
128*1f5207b7SJohn Levon static void clean_up_insns(struct entrypoint *ep)
129*1f5207b7SJohn Levon {
130*1f5207b7SJohn Levon 	struct basic_block *bb;
131*1f5207b7SJohn Levon 
132*1f5207b7SJohn Levon 	FOR_EACH_PTR(ep->bbs, bb) {
133*1f5207b7SJohn Levon 		struct instruction *insn;
134*1f5207b7SJohn Levon 		FOR_EACH_PTR(bb->insns, insn) {
135*1f5207b7SJohn Levon 			clean_up_one_instruction(bb, insn);
136*1f5207b7SJohn Levon 		} END_FOR_EACH_PTR(insn);
137*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(bb);
138*1f5207b7SJohn Levon }
139*1f5207b7SJohn Levon 
140*1f5207b7SJohn Levon /* Compare two (sorted) phi-lists */
141*1f5207b7SJohn Levon static int phi_list_compare(struct pseudo_list *l1, struct pseudo_list *l2)
142*1f5207b7SJohn Levon {
143*1f5207b7SJohn Levon 	pseudo_t phi1, phi2;
144*1f5207b7SJohn Levon 
145*1f5207b7SJohn Levon 	PREPARE_PTR_LIST(l1, phi1);
146*1f5207b7SJohn Levon 	PREPARE_PTR_LIST(l2, phi2);
147*1f5207b7SJohn Levon 	for (;;) {
148*1f5207b7SJohn Levon 		int cmp;
149*1f5207b7SJohn Levon 
150*1f5207b7SJohn Levon 		while (phi1 && (phi1 == VOID || !phi1->def))
151*1f5207b7SJohn Levon 			NEXT_PTR_LIST(phi1);
152*1f5207b7SJohn Levon 		while (phi2 && (phi2 == VOID || !phi2->def))
153*1f5207b7SJohn Levon 			NEXT_PTR_LIST(phi2);
154*1f5207b7SJohn Levon 
155*1f5207b7SJohn Levon 		if (!phi1)
156*1f5207b7SJohn Levon 			return phi2 ? -1 : 0;
157*1f5207b7SJohn Levon 		if (!phi2)
158*1f5207b7SJohn Levon 			return phi1 ? 1 : 0;
159*1f5207b7SJohn Levon 		cmp = phi_compare(phi1, phi2);
160*1f5207b7SJohn Levon 		if (cmp)
161*1f5207b7SJohn Levon 			return cmp;
162*1f5207b7SJohn Levon 		NEXT_PTR_LIST(phi1);
163*1f5207b7SJohn Levon 		NEXT_PTR_LIST(phi2);
164*1f5207b7SJohn Levon 	}
165*1f5207b7SJohn Levon 	/* Not reached, but we need to make the nesting come out right */
166*1f5207b7SJohn Levon 	FINISH_PTR_LIST(phi2);
167*1f5207b7SJohn Levon 	FINISH_PTR_LIST(phi1);
168*1f5207b7SJohn Levon }
169*1f5207b7SJohn Levon 
170*1f5207b7SJohn Levon static int insn_compare(const void *_i1, const void *_i2)
171*1f5207b7SJohn Levon {
172*1f5207b7SJohn Levon 	const struct instruction *i1 = _i1;
173*1f5207b7SJohn Levon 	const struct instruction *i2 = _i2;
174*1f5207b7SJohn Levon 
175*1f5207b7SJohn Levon 	if (i1->opcode != i2->opcode)
176*1f5207b7SJohn Levon 		return i1->opcode < i2->opcode ? -1 : 1;
177*1f5207b7SJohn Levon 
178*1f5207b7SJohn Levon 	switch (i1->opcode) {
179*1f5207b7SJohn Levon 
180*1f5207b7SJohn Levon 	/* commutative binop */
181*1f5207b7SJohn Levon 	case OP_ADD:
182*1f5207b7SJohn Levon 	case OP_MULU: case OP_MULS:
183*1f5207b7SJohn Levon 	case OP_AND_BOOL: case OP_OR_BOOL:
184*1f5207b7SJohn Levon 	case OP_AND: case OP_OR:
185*1f5207b7SJohn Levon 	case OP_XOR:
186*1f5207b7SJohn Levon 	case OP_SET_EQ: case OP_SET_NE:
187*1f5207b7SJohn Levon 		if (i1->src1 == i2->src2 && i1->src2 == i2->src1)
188*1f5207b7SJohn Levon 			return 0;
189*1f5207b7SJohn Levon 		goto case_binops;
190*1f5207b7SJohn Levon 
191*1f5207b7SJohn Levon 	case OP_SEL:
192*1f5207b7SJohn Levon 		if (i1->src3 != i2->src3)
193*1f5207b7SJohn Levon 			return i1->src3 < i2->src3 ? -1 : 1;
194*1f5207b7SJohn Levon 		/* Fall-through to binops */
195*1f5207b7SJohn Levon 
196*1f5207b7SJohn Levon 	/* Binary arithmetic */
197*1f5207b7SJohn Levon 	case OP_SUB:
198*1f5207b7SJohn Levon 	case OP_DIVU: case OP_DIVS:
199*1f5207b7SJohn Levon 	case OP_MODU: case OP_MODS:
200*1f5207b7SJohn Levon 	case OP_SHL:
201*1f5207b7SJohn Levon 	case OP_LSR: case OP_ASR:
202*1f5207b7SJohn Levon 
203*1f5207b7SJohn Levon 	/* Binary comparison */
204*1f5207b7SJohn Levon 	case OP_SET_LE: case OP_SET_GE:
205*1f5207b7SJohn Levon 	case OP_SET_LT: case OP_SET_GT:
206*1f5207b7SJohn Levon 	case OP_SET_B:  case OP_SET_A:
207*1f5207b7SJohn Levon 	case OP_SET_BE: case OP_SET_AE:
208*1f5207b7SJohn Levon 	case_binops:
209*1f5207b7SJohn Levon 		if (i1->src2 != i2->src2)
210*1f5207b7SJohn Levon 			return i1->src2 < i2->src2 ? -1 : 1;
211*1f5207b7SJohn Levon 		/* Fall through to unops */
212*1f5207b7SJohn Levon 
213*1f5207b7SJohn Levon 	/* Unary */
214*1f5207b7SJohn Levon 	case OP_NOT: case OP_NEG:
215*1f5207b7SJohn Levon 		if (i1->src1 != i2->src1)
216*1f5207b7SJohn Levon 			return i1->src1 < i2->src1 ? -1 : 1;
217*1f5207b7SJohn Levon 		break;
218*1f5207b7SJohn Levon 
219*1f5207b7SJohn Levon 	case OP_SYMADDR:
220*1f5207b7SJohn Levon 		if (i1->symbol != i2->symbol)
221*1f5207b7SJohn Levon 			return i1->symbol < i2->symbol ? -1 : 1;
222*1f5207b7SJohn Levon 		break;
223*1f5207b7SJohn Levon 
224*1f5207b7SJohn Levon 	case OP_SETVAL:
225*1f5207b7SJohn Levon 		if (i1->val != i2->val)
226*1f5207b7SJohn Levon 			return i1->val < i2->val ? -1 : 1;
227*1f5207b7SJohn Levon 		break;
228*1f5207b7SJohn Levon 
229*1f5207b7SJohn Levon 	/* Other */
230*1f5207b7SJohn Levon 	case OP_PHI:
231*1f5207b7SJohn Levon 		return phi_list_compare(i1->phi_list, i2->phi_list);
232*1f5207b7SJohn Levon 
233*1f5207b7SJohn Levon 	case OP_CAST:
234*1f5207b7SJohn Levon 	case OP_SCAST:
235*1f5207b7SJohn Levon 	case OP_PTRCAST:
236*1f5207b7SJohn Levon 		/*
237*1f5207b7SJohn Levon 		 * This is crap! See the comments on hashing.
238*1f5207b7SJohn Levon 		 */
239*1f5207b7SJohn Levon 		if (i1->orig_type != i2->orig_type)
240*1f5207b7SJohn Levon 			return i1->orig_type < i2->orig_type ? -1 : 1;
241*1f5207b7SJohn Levon 		if (i1->src != i2->src)
242*1f5207b7SJohn Levon 			return i1->src < i2->src ? -1 : 1;
243*1f5207b7SJohn Levon 		break;
244*1f5207b7SJohn Levon 
245*1f5207b7SJohn Levon 	default:
246*1f5207b7SJohn Levon 		warning(i1->pos, "bad instruction on hash chain");
247*1f5207b7SJohn Levon 	}
248*1f5207b7SJohn Levon 	if (i1->size != i2->size)
249*1f5207b7SJohn Levon 		return i1->size < i2->size ? -1 : 1;
250*1f5207b7SJohn Levon 	return 0;
251*1f5207b7SJohn Levon }
252*1f5207b7SJohn Levon 
253*1f5207b7SJohn Levon static void sort_instruction_list(struct instruction_list **list)
254*1f5207b7SJohn Levon {
255*1f5207b7SJohn Levon 	sort_list((struct ptr_list **)list , insn_compare);
256*1f5207b7SJohn Levon }
257*1f5207b7SJohn Levon 
258*1f5207b7SJohn Levon static struct instruction * cse_one_instruction(struct instruction *insn, struct instruction *def)
259*1f5207b7SJohn Levon {
260*1f5207b7SJohn Levon 	convert_instruction_target(insn, def->target);
261*1f5207b7SJohn Levon 
262*1f5207b7SJohn Levon 	kill_instruction(insn);
263*1f5207b7SJohn Levon 	repeat_phase |= REPEAT_CSE;
264*1f5207b7SJohn Levon 	return def;
265*1f5207b7SJohn Levon }
266*1f5207b7SJohn Levon 
267*1f5207b7SJohn Levon /*
268*1f5207b7SJohn Levon  * Does "bb1" dominate "bb2"?
269*1f5207b7SJohn Levon  */
270*1f5207b7SJohn Levon static int bb_dominates(struct entrypoint *ep, struct basic_block *bb1, struct basic_block *bb2, unsigned long generation)
271*1f5207b7SJohn Levon {
272*1f5207b7SJohn Levon 	struct basic_block *parent;
273*1f5207b7SJohn Levon 
274*1f5207b7SJohn Levon 	/* Nothing dominates the entrypoint.. */
275*1f5207b7SJohn Levon 	if (bb2 == ep->entry->bb)
276*1f5207b7SJohn Levon 		return 0;
277*1f5207b7SJohn Levon 	FOR_EACH_PTR(bb2->parents, parent) {
278*1f5207b7SJohn Levon 		if (parent == bb1)
279*1f5207b7SJohn Levon 			continue;
280*1f5207b7SJohn Levon 		if (parent->generation == generation)
281*1f5207b7SJohn Levon 			continue;
282*1f5207b7SJohn Levon 		parent->generation = generation;
283*1f5207b7SJohn Levon 		if (!bb_dominates(ep, bb1, parent, generation))
284*1f5207b7SJohn Levon 			return 0;
285*1f5207b7SJohn Levon 	} END_FOR_EACH_PTR(parent);
286*1f5207b7SJohn Levon 	return 1;
287*1f5207b7SJohn Levon }
288*1f5207b7SJohn Levon 
289*1f5207b7SJohn Levon static struct basic_block *trivial_common_parent(struct basic_block *bb1, struct basic_block *bb2)
290*1f5207b7SJohn Levon {
291*1f5207b7SJohn Levon 	struct basic_block *parent;
292*1f5207b7SJohn Levon 
293*1f5207b7SJohn Levon 	if (bb_list_size(bb1->parents) != 1)
294*1f5207b7SJohn Levon 		return NULL;
295*1f5207b7SJohn Levon 	parent = first_basic_block(bb1->parents);
296*1f5207b7SJohn Levon 	if (bb_list_size(bb2->parents) != 1)
297*1f5207b7SJohn Levon 		return NULL;
298*1f5207b7SJohn Levon 	if (first_basic_block(bb2->parents) != parent)
299*1f5207b7SJohn Levon 		return NULL;
300*1f5207b7SJohn Levon 	return parent;
301*1f5207b7SJohn Levon }
302*1f5207b7SJohn Levon 
303*1f5207b7SJohn Levon static inline void remove_instruction(struct instruction_list **list, struct instruction *insn, int count)
304*1f5207b7SJohn Levon {
305*1f5207b7SJohn Levon 	delete_ptr_list_entry((struct ptr_list **)list, insn, count);
306*1f5207b7SJohn Levon }
307*1f5207b7SJohn Levon 
308*1f5207b7SJohn Levon static void add_instruction_to_end(struct instruction *insn, struct basic_block *bb)
309*1f5207b7SJohn Levon {
310*1f5207b7SJohn Levon 	struct instruction *br = delete_last_instruction(&bb->insns);
311*1f5207b7SJohn Levon 	insn->bb = bb;
312*1f5207b7SJohn Levon 	add_instruction(&bb->insns, insn);
313*1f5207b7SJohn Levon 	add_instruction(&bb->insns, br);
314*1f5207b7SJohn Levon }
315*1f5207b7SJohn Levon 
316*1f5207b7SJohn Levon static struct instruction * try_to_cse(struct entrypoint *ep, struct instruction *i1, struct instruction *i2)
317*1f5207b7SJohn Levon {
318*1f5207b7SJohn Levon 	struct basic_block *b1, *b2, *common;
319*1f5207b7SJohn Levon 
320*1f5207b7SJohn Levon 	/*
321*1f5207b7SJohn Levon 	 * OK, i1 and i2 are the same instruction, modulo "target".
322*1f5207b7SJohn Levon 	 * We should now see if we can combine them.
323*1f5207b7SJohn Levon 	 */
324*1f5207b7SJohn Levon 	b1 = i1->bb;
325*1f5207b7SJohn Levon 	b2 = i2->bb;
326*1f5207b7SJohn Levon 
327*1f5207b7SJohn Levon 	/*
328*1f5207b7SJohn Levon 	 * Currently we only handle the uninteresting degenerate case where
329*1f5207b7SJohn Levon 	 * the CSE is inside one basic-block.
330*1f5207b7SJohn Levon 	 */
331*1f5207b7SJohn Levon 	if (b1 == b2) {
332*1f5207b7SJohn Levon 		struct instruction *insn;
333*1f5207b7SJohn Levon 		FOR_EACH_PTR(b1->insns, insn) {
334*1f5207b7SJohn Levon 			if (insn == i1)
335*1f5207b7SJohn Levon 				return cse_one_instruction(i2, i1);
336*1f5207b7SJohn Levon 			if (insn == i2)
337*1f5207b7SJohn Levon 				return cse_one_instruction(i1, i2);
338*1f5207b7SJohn Levon 		} END_FOR_EACH_PTR(insn);
339*1f5207b7SJohn Levon 		warning(b1->pos, "Whaa? unable to find CSE instructions");
340*1f5207b7SJohn Levon 		return i1;
341*1f5207b7SJohn Levon 	}
342*1f5207b7SJohn Levon 	if (bb_dominates(ep, b1, b2, ++bb_generation))
343*1f5207b7SJohn Levon 		return cse_one_instruction(i2, i1);
344*1f5207b7SJohn Levon 
345*1f5207b7SJohn Levon 	if (bb_dominates(ep, b2, b1, ++bb_generation))
346*1f5207b7SJohn Levon 		return cse_one_instruction(i1, i2);
347*1f5207b7SJohn Levon 
348*1f5207b7SJohn Levon 	/* No direct dominance - but we could try to find a common ancestor.. */
349*1f5207b7SJohn Levon 	common = trivial_common_parent(b1, b2);
350*1f5207b7SJohn Levon 	if (common) {
351*1f5207b7SJohn Levon 		i1 = cse_one_instruction(i2, i1);
352*1f5207b7SJohn Levon 		remove_instruction(&b1->insns, i1, 1);
353*1f5207b7SJohn Levon 		add_instruction_to_end(i1, common);
354*1f5207b7SJohn Levon 	}
355*1f5207b7SJohn Levon 
356*1f5207b7SJohn Levon 	return i1;
357*1f5207b7SJohn Levon }
358*1f5207b7SJohn Levon 
359*1f5207b7SJohn Levon void cleanup_and_cse(struct entrypoint *ep)
360*1f5207b7SJohn Levon {
361*1f5207b7SJohn Levon 	int i;
362*1f5207b7SJohn Levon 
363*1f5207b7SJohn Levon 	simplify_memops(ep);
364*1f5207b7SJohn Levon repeat:
365*1f5207b7SJohn Levon 	repeat_phase = 0;
366*1f5207b7SJohn Levon 	clean_up_insns(ep);
367*1f5207b7SJohn Levon 	if (repeat_phase & REPEAT_CFG_CLEANUP)
368*1f5207b7SJohn Levon 		kill_unreachable_bbs(ep);
369*1f5207b7SJohn Levon 	for (i = 0; i < INSN_HASH_SIZE; i++) {
370*1f5207b7SJohn Levon 		struct instruction_list **list = insn_hash_table + i;
371*1f5207b7SJohn Levon 		if (*list) {
372*1f5207b7SJohn Levon 			if (instruction_list_size(*list) > 1) {
373*1f5207b7SJohn Levon 				struct instruction *insn, *last;
374*1f5207b7SJohn Levon 
375*1f5207b7SJohn Levon 				sort_instruction_list(list);
376*1f5207b7SJohn Levon 
377*1f5207b7SJohn Levon 				last = NULL;
378*1f5207b7SJohn Levon 				FOR_EACH_PTR(*list, insn) {
379*1f5207b7SJohn Levon 					if (!insn->bb)
380*1f5207b7SJohn Levon 						continue;
381*1f5207b7SJohn Levon 					if (last) {
382*1f5207b7SJohn Levon 						if (!insn_compare(last, insn))
383*1f5207b7SJohn Levon 							insn = try_to_cse(ep, last, insn);
384*1f5207b7SJohn Levon 					}
385*1f5207b7SJohn Levon 					last = insn;
386*1f5207b7SJohn Levon 				} END_FOR_EACH_PTR(insn);
387*1f5207b7SJohn Levon 			}
388*1f5207b7SJohn Levon 			free_ptr_list((struct ptr_list **)list);
389*1f5207b7SJohn Levon 		}
390*1f5207b7SJohn Levon 	}
391*1f5207b7SJohn Levon 
392*1f5207b7SJohn Levon 	if (repeat_phase & REPEAT_SYMBOL_CLEANUP)
393*1f5207b7SJohn Levon 		simplify_memops(ep);
394*1f5207b7SJohn Levon 
395*1f5207b7SJohn Levon 	if (repeat_phase & REPEAT_CSE)
396*1f5207b7SJohn Levon 		goto repeat;
397*1f5207b7SJohn Levon }
398