Revision 53108fb5
b/tcg/optimize.c | ||
---|---|---|
96 | 96 |
{ |
97 | 97 |
switch (op) { |
98 | 98 |
case INDEX_op_mov_i32: |
99 |
case INDEX_op_add_i32: |
|
100 |
case INDEX_op_sub_i32: |
|
101 |
case INDEX_op_mul_i32: |
|
99 | 102 |
return 32; |
100 | 103 |
#if TCG_TARGET_REG_BITS == 64 |
101 | 104 |
case INDEX_op_mov_i64: |
105 |
case INDEX_op_add_i64: |
|
106 |
case INDEX_op_sub_i64: |
|
107 |
case INDEX_op_mul_i64: |
|
102 | 108 |
return 64; |
103 | 109 |
#endif |
104 | 110 |
default: |
... | ... | |
156 | 162 |
gen_args[1] = val; |
157 | 163 |
} |
158 | 164 |
|
165 |
static int op_to_mov(int op) |
|
166 |
{ |
|
167 |
switch (op_bits(op)) { |
|
168 |
case 32: |
|
169 |
return INDEX_op_mov_i32; |
|
170 |
#if TCG_TARGET_REG_BITS == 64 |
|
171 |
case 64: |
|
172 |
return INDEX_op_mov_i64; |
|
173 |
#endif |
|
174 |
default: |
|
175 |
fprintf(stderr, "op_to_mov: unexpected return value of " |
|
176 |
"function op_bits.\n"); |
|
177 |
tcg_abort(); |
|
178 |
} |
|
179 |
} |
|
180 |
|
|
181 |
static TCGArg do_constant_folding_2(int op, TCGArg x, TCGArg y) |
|
182 |
{ |
|
183 |
switch (op) { |
|
184 |
CASE_OP_32_64(add): |
|
185 |
return x + y; |
|
186 |
|
|
187 |
CASE_OP_32_64(sub): |
|
188 |
return x - y; |
|
189 |
|
|
190 |
CASE_OP_32_64(mul): |
|
191 |
return x * y; |
|
192 |
|
|
193 |
default: |
|
194 |
fprintf(stderr, |
|
195 |
"Unrecognized operation %d in do_constant_folding.\n", op); |
|
196 |
tcg_abort(); |
|
197 |
} |
|
198 |
} |
|
199 |
|
|
200 |
static TCGArg do_constant_folding(int op, TCGArg x, TCGArg y) |
|
201 |
{ |
|
202 |
TCGArg res = do_constant_folding_2(op, x, y); |
|
203 |
#if TCG_TARGET_REG_BITS == 64 |
|
204 |
if (op_bits(op) == 32) { |
|
205 |
res &= 0xffffffff; |
|
206 |
} |
|
207 |
#endif |
|
208 |
return res; |
|
209 |
} |
|
210 |
|
|
159 | 211 |
/* Propagate constants and copies, fold constant expressions. */ |
160 | 212 |
static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, |
161 | 213 |
TCGArg *args, TCGOpDef *tcg_op_defs) |
... | ... | |
163 | 215 |
int i, nb_ops, op_index, op, nb_temps, nb_globals, nb_call_args; |
164 | 216 |
const TCGOpDef *def; |
165 | 217 |
TCGArg *gen_args; |
218 |
TCGArg tmp; |
|
166 | 219 |
/* Array VALS has an element for each temp. |
167 | 220 |
If this temp holds a constant then its value is kept in VALS' element. |
168 | 221 |
If this temp is a copy of other ones then this equivalence class' |
... | ... | |
189 | 242 |
} |
190 | 243 |
} |
191 | 244 |
|
245 |
/* For commutative operations make constant second argument */ |
|
246 |
switch (op) { |
|
247 |
CASE_OP_32_64(add): |
|
248 |
CASE_OP_32_64(mul): |
|
249 |
if (temps[args[1]].state == TCG_TEMP_CONST) { |
|
250 |
tmp = args[1]; |
|
251 |
args[1] = args[2]; |
|
252 |
args[2] = tmp; |
|
253 |
} |
|
254 |
break; |
|
255 |
default: |
|
256 |
break; |
|
257 |
} |
|
258 |
|
|
259 |
/* Simplify expression if possible. */ |
|
260 |
switch (op) { |
|
261 |
CASE_OP_32_64(add): |
|
262 |
CASE_OP_32_64(sub): |
|
263 |
if (temps[args[1]].state == TCG_TEMP_CONST) { |
|
264 |
/* Proceed with possible constant folding. */ |
|
265 |
break; |
|
266 |
} |
|
267 |
if (temps[args[2]].state == TCG_TEMP_CONST |
|
268 |
&& temps[args[2]].val == 0) { |
|
269 |
if ((temps[args[0]].state == TCG_TEMP_COPY |
|
270 |
&& temps[args[0]].val == args[1]) |
|
271 |
|| args[0] == args[1]) { |
|
272 |
args += 3; |
|
273 |
gen_opc_buf[op_index] = INDEX_op_nop; |
|
274 |
} else { |
|
275 |
gen_opc_buf[op_index] = op_to_mov(op); |
|
276 |
tcg_opt_gen_mov(gen_args, args[0], args[1], |
|
277 |
nb_temps, nb_globals); |
|
278 |
gen_args += 2; |
|
279 |
args += 3; |
|
280 |
} |
|
281 |
continue; |
|
282 |
} |
|
283 |
break; |
|
284 |
CASE_OP_32_64(mul): |
|
285 |
if ((temps[args[2]].state == TCG_TEMP_CONST |
|
286 |
&& temps[args[2]].val == 0)) { |
|
287 |
gen_opc_buf[op_index] = op_to_movi(op); |
|
288 |
tcg_opt_gen_movi(gen_args, args[0], 0, nb_temps, nb_globals); |
|
289 |
args += 3; |
|
290 |
gen_args += 2; |
|
291 |
continue; |
|
292 |
} |
|
293 |
break; |
|
294 |
} |
|
295 |
|
|
192 | 296 |
/* Propagate constants through copy operations and do constant |
193 | 297 |
folding. Constants will be substituted to arguments by register |
194 | 298 |
allocator where needed and possible. Also detect copies. */ |
... | ... | |
219 | 323 |
gen_args += 2; |
220 | 324 |
args += 2; |
221 | 325 |
break; |
326 |
CASE_OP_32_64(add): |
|
327 |
CASE_OP_32_64(sub): |
|
328 |
CASE_OP_32_64(mul): |
|
329 |
if (temps[args[1]].state == TCG_TEMP_CONST |
|
330 |
&& temps[args[2]].state == TCG_TEMP_CONST) { |
|
331 |
gen_opc_buf[op_index] = op_to_movi(op); |
|
332 |
tmp = do_constant_folding(op, temps[args[1]].val, |
|
333 |
temps[args[2]].val); |
|
334 |
tcg_opt_gen_movi(gen_args, args[0], tmp, nb_temps, nb_globals); |
|
335 |
gen_args += 2; |
|
336 |
args += 3; |
|
337 |
break; |
|
338 |
} else { |
|
339 |
reset_temp(args[0], nb_temps, nb_globals); |
|
340 |
gen_args[0] = args[0]; |
|
341 |
gen_args[1] = args[1]; |
|
342 |
gen_args[2] = args[2]; |
|
343 |
gen_args += 3; |
|
344 |
args += 3; |
|
345 |
break; |
|
346 |
} |
|
222 | 347 |
case INDEX_op_call: |
223 | 348 |
nb_call_args = (args[0] >> 16) + (args[0] & 0xffff); |
224 | 349 |
if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) { |
Also available in: Unified diff