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
;
25 FOR_EACH_PTR(bb
->parents
, parent
) {
26 struct instruction
*one
;
27 struct instruction
*br
;
30 FOR_EACH_PTR_REVERSE(parent
->insns
, one
) {
36 dominance
= dominates(pseudo
, insn
, one
, local
);
38 if (one
->opcode
== OP_LOAD
)
45 } END_FOR_EACH_PTR_REVERSE(one
);
47 if (parent
->generation
== generation
)
49 parent
->generation
= generation
;
51 if (!find_dominating_parents(pseudo
, insn
, parent
, generation
, dominators
, local
))
56 br
= delete_last_instruction(&parent
->insns
);
57 phi
= alloc_phi(parent
, one
->target
, one
->type
);
58 phi
->ident
= phi
->ident
? : one
->target
->ident
;
59 add_instruction(&parent
->insns
, br
);
60 use_pseudo(insn
, phi
, add_pseudo(dominators
, phi
));
61 } END_FOR_EACH_PTR(parent
);
65 static int address_taken(pseudo_t pseudo
)
67 struct pseudo_user
*pu
;
68 FOR_EACH_PTR(pseudo
->users
, pu
) {
69 struct instruction
*insn
= pu
->insn
;
70 if (insn
->bb
&& (insn
->opcode
!= OP_LOAD
&& insn
->opcode
!= OP_STORE
))
72 if (pu
->userp
!= &insn
->src
)
74 } END_FOR_EACH_PTR(pu
);
78 static int local_pseudo(pseudo_t pseudo
)
80 return pseudo
->type
== PSEUDO_SYM
81 && !(pseudo
->sym
->ctype
.modifiers
& (MOD_STATIC
| MOD_NONLOCAL
))
82 && !address_taken(pseudo
);
85 static void simplify_loads(struct basic_block
*bb
)
87 struct instruction
*insn
;
89 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
92 if (insn
->opcode
== OP_LOAD
) {
93 struct instruction
*dom
;
94 pseudo_t pseudo
= insn
->src
;
95 int local
= local_pseudo(pseudo
);
96 struct pseudo_list
*dominators
;
97 unsigned long generation
;
99 /* Check for illegal offsets.. */
102 if (insn
->is_volatile
)
105 RECURSE_PTR_REVERSE(insn
, dom
) {
109 dominance
= dominates(pseudo
, insn
, dom
, local
);
111 /* possible partial dominance? */
113 if (dom
->opcode
== OP_LOAD
)
117 /* Yeehaa! Found one! */
118 convert_load_instruction(insn
, dom
->target
);
121 } END_FOR_EACH_PTR_REVERSE(dom
);
123 /* OK, go find the parents */
124 generation
= ++bb_generation
;
125 bb
->generation
= generation
;
127 if (find_dominating_parents(pseudo
, insn
, bb
, generation
, &dominators
, local
)) {
128 /* This happens with initial assignments to structures etc.. */
131 assert(pseudo
->type
!= PSEUDO_ARG
);
132 convert_load_instruction(insn
, value_pseudo(0));
136 rewrite_load_instruction(insn
, dominators
);
137 } else { // cleanup pending phi-sources
139 FOR_EACH_PTR(dominators
, phi
) {
140 kill_instruction(phi
->def
);
141 } END_FOR_EACH_PTR(phi
);
145 /* Do the next one */;
146 } END_FOR_EACH_PTR_REVERSE(insn
);
149 static void kill_dominated_stores(struct basic_block
*bb
)
151 struct instruction
*insn
;
153 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
156 if (insn
->opcode
== OP_STORE
) {
157 struct instruction
*dom
;
158 pseudo_t pseudo
= insn
->src
;
163 if (insn
->is_volatile
)
166 local
= local_pseudo(pseudo
);
167 RECURSE_PTR_REVERSE(insn
, dom
) {
171 dominance
= dominates(pseudo
, insn
, dom
, local
);
173 /* possible partial dominance? */
176 if (dom
->opcode
== OP_LOAD
)
178 /* Yeehaa! Found one! */
179 kill_instruction_force(dom
);
181 } END_FOR_EACH_PTR_REVERSE(dom
);
183 /* OK, we should check the parents now */
186 /* Do the next one */;
187 } END_FOR_EACH_PTR_REVERSE(insn
);
190 void simplify_memops(struct entrypoint
*ep
)
192 struct basic_block
*bb
;
195 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
197 } END_FOR_EACH_PTR_REVERSE(bb
);
199 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
200 kill_dominated_stores(bb
);
201 } END_FOR_EACH_PTR_REVERSE(bb
);
203 FOR_EACH_PTR(ep
->accesses
, pseudo
) {
204 struct symbol
*var
= pseudo
->sym
;
208 mod
= var
->ctype
.modifiers
;
209 if (mod
& (MOD_VOLATILE
| MOD_NONLOCAL
| MOD_STATIC
))
211 kill_dead_stores(ep
, pseudo
, local_pseudo(pseudo
));
212 } END_FOR_EACH_PTR(pseudo
);