37 if (dominance < 0) {
38 if (one->opcode == OP_LOAD)
39 continue;
40 return 0;
41 }
42 if (!dominance)
43 continue;
44 goto found_dominator;
45 } END_FOR_EACH_PTR_REVERSE(one);
46 no_dominance:
47 if (parent->generation == generation)
48 continue;
49 parent->generation = generation;
50
51 if (!find_dominating_parents(pseudo, insn, parent, generation, dominators, local))
52 return 0;
53 continue;
54
55 found_dominator:
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);
62 return 1;
63 }
64
65 static int address_taken(pseudo_t pseudo)
66 {
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))
71 return 1;
72 } END_FOR_EACH_PTR(pu);
73 return 0;
74 }
75
76 static int local_pseudo(pseudo_t pseudo)
77 {
78 return pseudo->type == PSEUDO_SYM
79 && !(pseudo->sym->ctype.modifiers & (MOD_STATIC | MOD_NONLOCAL))
80 && !address_taken(pseudo);
81 }
82
83 static void simplify_loads(struct basic_block *bb)
84 {
85 struct instruction *insn;
86
87 FOR_EACH_PTR_REVERSE(bb->insns, insn) {
88 if (!insn->bb)
89 continue;
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;
96
97 /* Check for illegal offsets.. */
98 check_access(insn);
99
100 if (insn->type->ctype.modifiers & MOD_VOLATILE)
101 continue;
102
103 RECURSE_PTR_REVERSE(insn, dom) {
104 int dominance;
105 if (!dom->bb)
106 continue;
107 dominance = dominates(pseudo, insn, dom, local);
108 if (dominance) {
109 /* possible partial dominance? */
110 if (dominance < 0) {
111 if (dom->opcode == OP_LOAD)
112 continue;
113 goto next_load;
114 }
115 /* Yeehaa! Found one! */
116 convert_load_instruction(insn, dom->target);
117 goto next_load;
118 }
119 } END_FOR_EACH_PTR_REVERSE(dom);
120
121 /* OK, go find the parents */
122 generation = ++bb_generation;
123 bb->generation = generation;
124 dominators = NULL;
125 if (find_dominating_parents(pseudo, insn, bb, generation, &dominators, local)) {
126 /* This happens with initial assignments to structures etc.. */
127 if (!dominators) {
128 if (local) {
129 assert(pseudo->type != PSEUDO_ARG);
130 convert_load_instruction(insn, value_pseudo(insn->type, 0));
131 }
132 goto next_load;
133 }
134 rewrite_load_instruction(insn, dominators);
135 }
136 }
137 next_load:
138 /* Do the next one */;
139 } END_FOR_EACH_PTR_REVERSE(insn);
140 }
141
142 static void kill_store(struct instruction *insn)
143 {
144 if (insn) {
145 insn->bb = NULL;
146 insn->opcode = OP_SNOP;
147 kill_use(&insn->target);
148 }
149 }
150
151 static void kill_dominated_stores(struct basic_block *bb)
152 {
153 struct instruction *insn;
154
155 FOR_EACH_PTR_REVERSE(bb->insns, insn) {
156 if (!insn->bb)
157 continue;
158 if (insn->opcode == OP_STORE) {
159 struct instruction *dom;
160 pseudo_t pseudo = insn->src;
161 int local = local_pseudo(pseudo);
162
163 RECURSE_PTR_REVERSE(insn, dom) {
164 int dominance;
165 if (!dom->bb)
166 continue;
167 dominance = dominates(pseudo, insn, dom, local);
168 if (dominance) {
169 /* possible partial dominance? */
170 if (dominance < 0)
171 goto next_store;
172 if (dom->opcode == OP_LOAD)
173 goto next_store;
174 /* Yeehaa! Found one! */
175 kill_store(dom);
176 }
177 } END_FOR_EACH_PTR_REVERSE(dom);
178
179 /* OK, we should check the parents now */
180 }
181 next_store:
182 /* Do the next one */;
183 } END_FOR_EACH_PTR_REVERSE(insn);
184 }
185
186 void simplify_memops(struct entrypoint *ep)
187 {
188 struct basic_block *bb;
189
190 FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
191 simplify_loads(bb);
192 } END_FOR_EACH_PTR_REVERSE(bb);
193
194 FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
195 kill_dominated_stores(bb);
196 } END_FOR_EACH_PTR_REVERSE(bb);
197 }
|
37 if (dominance < 0) {
38 if (one->opcode == OP_LOAD)
39 continue;
40 return 0;
41 }
42 if (!dominance)
43 continue;
44 goto found_dominator;
45 } END_FOR_EACH_PTR_REVERSE(one);
46 no_dominance:
47 if (parent->generation == generation)
48 continue;
49 parent->generation = generation;
50
51 if (!find_dominating_parents(pseudo, insn, parent, generation, dominators, local))
52 return 0;
53 continue;
54
55 found_dominator:
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);
62 return 1;
63 }
64
65 static int address_taken(pseudo_t pseudo)
66 {
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))
71 return 1;
72 if (pu->userp != &insn->src)
73 return 1;
74 } END_FOR_EACH_PTR(pu);
75 return 0;
76 }
77
78 static int local_pseudo(pseudo_t pseudo)
79 {
80 return pseudo->type == PSEUDO_SYM
81 && !(pseudo->sym->ctype.modifiers & (MOD_STATIC | MOD_NONLOCAL))
82 && !address_taken(pseudo);
83 }
84
85 static void simplify_loads(struct basic_block *bb)
86 {
87 struct instruction *insn;
88
89 FOR_EACH_PTR_REVERSE(bb->insns, insn) {
90 if (!insn->bb)
91 continue;
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;
98
99 /* Check for illegal offsets.. */
100 check_access(insn);
101
102 if (insn->is_volatile)
103 continue;
104
105 RECURSE_PTR_REVERSE(insn, dom) {
106 int dominance;
107 if (!dom->bb)
108 continue;
109 dominance = dominates(pseudo, insn, dom, local);
110 if (dominance) {
111 /* possible partial dominance? */
112 if (dominance < 0) {
113 if (dom->opcode == OP_LOAD)
114 continue;
115 goto next_load;
116 }
117 /* Yeehaa! Found one! */
118 convert_load_instruction(insn, dom->target);
119 goto next_load;
120 }
121 } END_FOR_EACH_PTR_REVERSE(dom);
122
123 /* OK, go find the parents */
124 generation = ++bb_generation;
125 bb->generation = generation;
126 dominators = NULL;
127 if (find_dominating_parents(pseudo, insn, bb, generation, &dominators, local)) {
128 /* This happens with initial assignments to structures etc.. */
129 if (!dominators) {
130 if (local) {
131 assert(pseudo->type != PSEUDO_ARG);
132 convert_load_instruction(insn, value_pseudo(0));
133 }
134 goto next_load;
135 }
136 rewrite_load_instruction(insn, dominators);
137 } else { // cleanup pending phi-sources
138 pseudo_t phi;
139 FOR_EACH_PTR(dominators, phi) {
140 kill_instruction(phi->def);
141 } END_FOR_EACH_PTR(phi);
142 }
143 }
144 next_load:
145 /* Do the next one */;
146 } END_FOR_EACH_PTR_REVERSE(insn);
147 }
148
149 static void kill_dominated_stores(struct basic_block *bb)
150 {
151 struct instruction *insn;
152
153 FOR_EACH_PTR_REVERSE(bb->insns, insn) {
154 if (!insn->bb)
155 continue;
156 if (insn->opcode == OP_STORE) {
157 struct instruction *dom;
158 pseudo_t pseudo = insn->src;
159 int local;
160
161 if (!insn->type)
162 continue;
163 if (insn->is_volatile)
164 continue;
165
166 local = local_pseudo(pseudo);
167 RECURSE_PTR_REVERSE(insn, dom) {
168 int dominance;
169 if (!dom->bb)
170 continue;
171 dominance = dominates(pseudo, insn, dom, local);
172 if (dominance) {
173 /* possible partial dominance? */
174 if (dominance < 0)
175 goto next_store;
176 if (dom->opcode == OP_LOAD)
177 goto next_store;
178 /* Yeehaa! Found one! */
179 kill_instruction_force(dom);
180 }
181 } END_FOR_EACH_PTR_REVERSE(dom);
182
183 /* OK, we should check the parents now */
184 }
185 next_store:
186 /* Do the next one */;
187 } END_FOR_EACH_PTR_REVERSE(insn);
188 }
189
190 void simplify_memops(struct entrypoint *ep)
191 {
192 struct basic_block *bb;
193 pseudo_t pseudo;
194
195 FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
196 simplify_loads(bb);
197 } END_FOR_EACH_PTR_REVERSE(bb);
198
199 FOR_EACH_PTR_REVERSE(ep->bbs, bb) {
200 kill_dominated_stores(bb);
201 } END_FOR_EACH_PTR_REVERSE(bb);
202
203 FOR_EACH_PTR(ep->accesses, pseudo) {
204 struct symbol *var = pseudo->sym;
205 unsigned long mod;
206 if (!var)
207 continue;
208 mod = var->ctype.modifiers;
209 if (mod & (MOD_VOLATILE | MOD_NONLOCAL | MOD_STATIC))
210 continue;
211 kill_dead_stores(ep, pseudo, local_pseudo(pseudo));
212 } END_FOR_EACH_PTR(pseudo);
213 }
|