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
->size
);
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 } END_FOR_EACH_PTR(pu
);
76 static int local_pseudo(pseudo_t pseudo
)
78 return pseudo
->type
== PSEUDO_SYM
79 && !(pseudo
->sym
->ctype
.modifiers
& (MOD_STATIC
| MOD_NONLOCAL
))
80 && !address_taken(pseudo
);
83 static void simplify_loads(struct basic_block
*bb
)
85 struct instruction
*insn
;
87 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
90 if (insn
->opcode
== OP_LOAD
) {
91 struct instruction
*dom
;
92 pseudo_t pseudo
= insn
->src
;
93 int local
= local_pseudo(pseudo
);
94 struct pseudo_list
*dominators
;
95 unsigned long generation
;
97 /* Check for illegal offsets.. */
100 if (insn
->type
->ctype
.modifiers
& MOD_VOLATILE
)
103 RECURSE_PTR_REVERSE(insn
, dom
) {
107 dominance
= dominates(pseudo
, insn
, dom
, local
);
109 /* possible partial dominance? */
111 if (dom
->opcode
== OP_LOAD
)
115 /* Yeehaa! Found one! */
116 convert_load_instruction(insn
, dom
->target
);
119 } END_FOR_EACH_PTR_REVERSE(dom
);
121 /* OK, go find the parents */
122 generation
= ++bb_generation
;
123 bb
->generation
= generation
;
125 if (find_dominating_parents(pseudo
, insn
, bb
, generation
, &dominators
, local
)) {
126 /* This happens with initial assignments to structures etc.. */
129 assert(pseudo
->type
!= PSEUDO_ARG
);
130 convert_load_instruction(insn
, value_pseudo(insn
->type
, 0));
134 rewrite_load_instruction(insn
, dominators
);
138 /* Do the next one */;
139 } END_FOR_EACH_PTR_REVERSE(insn
);
142 static void kill_store(struct instruction
*insn
)
146 insn
->opcode
= OP_SNOP
;
147 kill_use(&insn
->target
);
151 static void kill_dominated_stores(struct basic_block
*bb
)
153 struct instruction
*insn
;
155 FOR_EACH_PTR_REVERSE(bb
->insns
, insn
) {
158 if (insn
->opcode
== OP_STORE
) {
159 struct instruction
*dom
;
160 pseudo_t pseudo
= insn
->src
;
161 int local
= local_pseudo(pseudo
);
163 RECURSE_PTR_REVERSE(insn
, dom
) {
167 dominance
= dominates(pseudo
, insn
, dom
, local
);
169 /* possible partial dominance? */
172 if (dom
->opcode
== OP_LOAD
)
174 /* Yeehaa! Found one! */
177 } END_FOR_EACH_PTR_REVERSE(dom
);
179 /* OK, we should check the parents now */
182 /* Do the next one */;
183 } END_FOR_EACH_PTR_REVERSE(insn
);
186 void simplify_memops(struct entrypoint
*ep
)
188 struct basic_block
*bb
;
190 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
192 } END_FOR_EACH_PTR_REVERSE(bb
);
194 FOR_EACH_PTR_REVERSE(ep
->bbs
, bb
) {
195 kill_dominated_stores(bb
);
196 } END_FOR_EACH_PTR_REVERSE(bb
);