2 * memops - try to combine memory ops.
4 * Copyright (C) 2004 Linus Torvalds
15 #include "expression.h"
16 #include "linearize.h"
19 static int find_dominating_parents(pseudo_t pseudo
, struct instruction
*insn
,
20 struct basic_block
*bb
, unsigned long generation
, struct pseudo_list
**dominators
,
23 struct basic_block
*parent
;
26 * The entrypoint is special - it dominates all non-local
27 * pseudos, but no local ones.
29 if (bb
== bb
->ep
->entry
)
32 if (bb_list_size(bb
->parents
) > 1)
34 FOR_EACH_PTR(bb
->parents
, parent
) {
35 struct instruction
*one
;
36 struct instruction
*br
;
39 FOR_EACH_PTR_REVERSE(parent
->insns
, one
) {
43 dominance
= dominates(pseudo
, insn
, one
, local
);
45 if (one
->opcode
== OP_LOAD
)
51 if (one
->opcode
== OP_LOAD
&& !loads
)
54 } END_FOR_EACH_PTR_REVERSE(one
);
56 if (parent
->generation
== generation
)
58 parent
->generation
= generation
;
60 if (!find_dominating_parents(pseudo
, insn
, parent
, generation
, dominators
, local
, loads
))
65 br
= delete_last_instruction(&parent
->insns
);
66 phi
= alloc_phi(parent
, one
->target
, one
->size
);
67 phi
->ident
= phi
->ident
? : one
->target
->ident
;
68 add_instruction(&parent
->insns
, br
);
69 use_pseudo(phi
, add_pseudo(dominators
, phi
));
70 } END_FOR_EACH_PTR(parent
);
74 static inline int address_taken(pseudo_t pseudo
)
77 FOR_EACH_PTR(pseudo
->users
, usep
) {
78 struct instruction
*insn
= container(usep
, struct instruction
, src
);
79 if (insn
->bb
&& insn
->opcode
== OP_SETVAL
)
81 } END_FOR_EACH_PTR(usep
);
85 static int local_pseudo(pseudo_t pseudo
)
87 return pseudo
->type
== PSEUDO_SYM
88 && !(pseudo
->sym
->ctype
.modifiers
& (MOD_STATIC
| MOD_NONLOCAL
))
89 && !address_taken(pseudo
);
92 static void simplify_loads(struct basic_block
*bb
)
94 struct instruction
*insn
;
96 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
99 if (insn
->opcode
== OP_LOAD
) {
100 struct instruction
*dom
;
101 pseudo_t pseudo
= insn
->src
;
102 int local
= local_pseudo(pseudo
);
103 struct pseudo_list
*dominators
;
104 unsigned long generation
;
106 RECURSE_PTR_REVERSE(insn
, dom
) {
110 dominance
= dominates(pseudo
, insn
, dom
, local
);
112 /* possible partial dominance? */
114 if (dom
->opcode
== OP_LOAD
)
118 /* Yeehaa! Found one! */
119 convert_load_instruction(insn
, dom
->target
);
122 } END_FOR_EACH_PTR_REVERSE(dom
);
124 /* Ok, go find the parents */
125 generation
= ++bb_generation
;
126 bb
->generation
= generation
;
128 if (find_dominating_parents(pseudo
, insn
, bb
, generation
, &dominators
, local
, 1)) {
129 /* This happens with initial assignments to structures etc.. */
132 assert(pseudo
->type
!= PSEUDO_ARG
);
133 convert_load_instruction(insn
, value_pseudo(0));
137 rewrite_load_instruction(insn
, dominators
);
141 /* Do the next one */;
142 } END_FOR_EACH_PTR_REVERSE(insn
);
145 static void kill_store(struct instruction
*insn
)
149 insn
->opcode
= OP_SNOP
;
150 kill_use(&insn
->target
);
154 static void kill_dominated_stores(struct basic_block
*bb
)
156 struct instruction
*insn
;
158 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
161 if (insn
->opcode
== OP_STORE
) {
162 struct instruction
*dom
;
163 pseudo_t pseudo
= insn
->src
;
164 int local
= local_pseudo(pseudo
);
166 RECURSE_PTR_REVERSE(insn
, dom
) {
170 dominance
= dominates(pseudo
, insn
, dom
, local
);
172 /* possible partial dominance? */
175 if (dom
->opcode
== OP_LOAD
)
177 /* Yeehaa! Found one! */
180 } END_FOR_EACH_PTR_REVERSE(dom
);
182 /* Ok, we should check the parents now */
185 /* Do the next one */;
186 } END_FOR_EACH_PTR_REVERSE(insn
);
189 void simplify_memops(struct entrypoint
*ep
)
191 struct basic_block
*bb
;
193 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
195 } END_FOR_EACH_PTR_REVERSE(bb
);
197 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
198 kill_dominated_stores(bb
);
199 } END_FOR_EACH_PTR_REVERSE(bb
);