]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/optimize.c
tcg: Use per-temp state data in optimize
[mirror_qemu.git] / tcg / optimize.c
CommitLineData
8f2e8c07
KB
1/*
2 * Optimizations for Tiny Code Generator for QEMU
3 *
4 * Copyright (c) 2010 Samsung Electronics.
5 * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 */
25
757e725b 26#include "qemu/osdep.h"
8f2e8c07 27#include "qemu-common.h"
00f6da6a 28#include "exec/cpu-common.h"
8f2e8c07
KB
29#include "tcg-op.h"
30
8f2e8c07
KB
31#define CASE_OP_32_64(x) \
32 glue(glue(case INDEX_op_, x), _i32): \
33 glue(glue(case INDEX_op_, x), _i64)
8f2e8c07 34
22613af4 35struct tcg_temp_info {
b41059dd 36 bool is_const;
6349039d
RH
37 TCGTemp *prev_copy;
38 TCGTemp *next_copy;
22613af4 39 tcg_target_ulong val;
3a9d8b17 40 tcg_target_ulong mask;
22613af4
KB
41};
42
43static struct tcg_temp_info temps[TCG_MAX_TEMPS];
1208d7dd 44static TCGTempSet temps_used;
22613af4 45
6349039d 46static inline struct tcg_temp_info *ts_info(TCGTemp *ts)
d9c769c6 47{
6349039d 48 return ts->state_ptr;
d9c769c6
AJ
49}
50
6349039d 51static inline struct tcg_temp_info *arg_info(TCGArg arg)
d9c769c6 52{
6349039d
RH
53 return ts_info(arg_temp(arg));
54}
55
56static inline bool ts_is_const(TCGTemp *ts)
57{
58 return ts_info(ts)->is_const;
59}
60
61static inline bool arg_is_const(TCGArg arg)
62{
63 return ts_is_const(arg_temp(arg));
64}
65
66static inline bool ts_is_copy(TCGTemp *ts)
67{
68 return ts_info(ts)->next_copy != ts;
d9c769c6
AJ
69}
70
b41059dd 71/* Reset TEMP's state, possibly removing the temp for the list of copies. */
6349039d
RH
72static void reset_ts(TCGTemp *ts)
73{
74 struct tcg_temp_info *ti = ts_info(ts);
75 struct tcg_temp_info *pi = ts_info(ti->prev_copy);
76 struct tcg_temp_info *ni = ts_info(ti->next_copy);
77
78 ni->prev_copy = ti->prev_copy;
79 pi->next_copy = ti->next_copy;
80 ti->next_copy = ts;
81 ti->prev_copy = ts;
82 ti->is_const = false;
83 ti->mask = -1;
84}
85
86static void reset_temp(TCGArg arg)
22613af4 87{
6349039d 88 reset_ts(arg_temp(arg));
22613af4
KB
89}
90
1208d7dd
AJ
91/* Reset all temporaries, given that there are NB_TEMPS of them. */
92static void reset_all_temps(int nb_temps)
93{
94 bitmap_zero(temps_used.l, nb_temps);
95}
96
97/* Initialize and activate a temporary. */
6349039d 98static void init_ts_info(TCGTemp *ts)
1208d7dd 99{
6349039d
RH
100 size_t idx = temp_idx(ts);
101 if (!test_bit(idx, temps_used.l)) {
102 struct tcg_temp_info *ti = &temps[idx];
103
104 ts->state_ptr = ti;
105 ti->next_copy = ts;
106 ti->prev_copy = ts;
107 ti->is_const = false;
108 ti->mask = -1;
109 set_bit(idx, temps_used.l);
1208d7dd
AJ
110 }
111}
112
6349039d
RH
113static void init_arg_info(TCGArg arg)
114{
115 init_ts_info(arg_temp(arg));
116}
117
fe0de7aa 118static int op_bits(TCGOpcode op)
22613af4 119{
8399ad59
RH
120 const TCGOpDef *def = &tcg_op_defs[op];
121 return def->flags & TCG_OPF_64BIT ? 64 : 32;
22613af4
KB
122}
123
a62f6f56
RH
124static TCGOpcode op_to_mov(TCGOpcode op)
125{
126 switch (op_bits(op)) {
127 case 32:
128 return INDEX_op_mov_i32;
129 case 64:
130 return INDEX_op_mov_i64;
131 default:
132 fprintf(stderr, "op_to_mov: unexpected return value of "
133 "function op_bits.\n");
134 tcg_abort();
135 }
136}
137
fe0de7aa 138static TCGOpcode op_to_movi(TCGOpcode op)
22613af4
KB
139{
140 switch (op_bits(op)) {
141 case 32:
142 return INDEX_op_movi_i32;
22613af4
KB
143 case 64:
144 return INDEX_op_movi_i64;
22613af4
KB
145 default:
146 fprintf(stderr, "op_to_movi: unexpected return value of "
147 "function op_bits.\n");
148 tcg_abort();
149 }
150}
151
6349039d 152static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
e590d4e6 153{
6349039d 154 TCGTemp *i;
e590d4e6
AJ
155
156 /* If this is already a global, we can't do better. */
fa477d25 157 if (ts->temp_global) {
6349039d 158 return ts;
e590d4e6
AJ
159 }
160
161 /* Search for a global first. */
6349039d
RH
162 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
163 if (i->temp_global) {
e590d4e6
AJ
164 return i;
165 }
166 }
167
168 /* If it is a temp, search for a temp local. */
fa477d25 169 if (!ts->temp_local) {
6349039d
RH
170 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
171 if (ts->temp_local) {
e590d4e6
AJ
172 return i;
173 }
174 }
175 }
176
177 /* Failure to find a better representation, return the same temp. */
6349039d 178 return ts;
e590d4e6
AJ
179}
180
6349039d 181static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
e590d4e6 182{
6349039d 183 TCGTemp *i;
e590d4e6 184
6349039d 185 if (ts1 == ts2) {
e590d4e6
AJ
186 return true;
187 }
188
6349039d 189 if (!ts_is_copy(ts1) || !ts_is_copy(ts2)) {
e590d4e6
AJ
190 return false;
191 }
192
6349039d
RH
193 for (i = ts_info(ts1)->next_copy; i != ts1; i = ts_info(i)->next_copy) {
194 if (i == ts2) {
e590d4e6
AJ
195 return true;
196 }
197 }
198
199 return false;
200}
201
6349039d
RH
202static bool args_are_copies(TCGArg arg1, TCGArg arg2)
203{
204 return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
205}
206
acd93701 207static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val)
97a79eb7
AJ
208{
209 TCGOpcode new_op = op_to_movi(op->opc);
210 tcg_target_ulong mask;
6349039d 211 struct tcg_temp_info *di = arg_info(dst);
97a79eb7
AJ
212
213 op->opc = new_op;
214
215 reset_temp(dst);
6349039d
RH
216 di->is_const = true;
217 di->val = val;
97a79eb7 218 mask = val;
96152126 219 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
97a79eb7
AJ
220 /* High bits of the destination are now garbage. */
221 mask |= ~0xffffffffull;
222 }
6349039d 223 di->mask = mask;
97a79eb7 224
acd93701
RH
225 op->args[0] = dst;
226 op->args[1] = val;
97a79eb7
AJ
227}
228
acd93701 229static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
22613af4 230{
6349039d
RH
231 TCGTemp *dst_ts = arg_temp(dst);
232 TCGTemp *src_ts = arg_temp(src);
233 struct tcg_temp_info *di;
234 struct tcg_temp_info *si;
235 tcg_target_ulong mask;
236 TCGOpcode new_op;
237
238 if (ts_are_copies(dst_ts, src_ts)) {
5365718a
AJ
239 tcg_op_remove(s, op);
240 return;
241 }
242
6349039d
RH
243 reset_ts(dst_ts);
244 di = ts_info(dst_ts);
245 si = ts_info(src_ts);
246 new_op = op_to_mov(op->opc);
a62f6f56 247
c45cb8bb 248 op->opc = new_op;
6349039d
RH
249 op->args[0] = dst;
250 op->args[1] = src;
a62f6f56 251
6349039d 252 mask = si->mask;
24666baf
RH
253 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
254 /* High bits of the destination are now garbage. */
255 mask |= ~0xffffffffull;
256 }
6349039d 257 di->mask = mask;
e590d4e6 258
6349039d
RH
259 if (src_ts->type == dst_ts->type) {
260 struct tcg_temp_info *ni = ts_info(si->next_copy);
261
262 di->next_copy = si->next_copy;
263 di->prev_copy = src_ts;
264 ni->prev_copy = dst_ts;
265 si->next_copy = dst_ts;
266 di->is_const = si->is_const;
267 di->val = si->val;
268 }
22613af4
KB
269}
270
fe0de7aa 271static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
53108fb5 272{
03271524
RH
273 uint64_t l64, h64;
274
53108fb5
KB
275 switch (op) {
276 CASE_OP_32_64(add):
277 return x + y;
278
279 CASE_OP_32_64(sub):
280 return x - y;
281
282 CASE_OP_32_64(mul):
283 return x * y;
284
9a81090b
KB
285 CASE_OP_32_64(and):
286 return x & y;
287
288 CASE_OP_32_64(or):
289 return x | y;
290
291 CASE_OP_32_64(xor):
292 return x ^ y;
293
55c0975c 294 case INDEX_op_shl_i32:
50c5c4d1 295 return (uint32_t)x << (y & 31);
55c0975c 296
55c0975c 297 case INDEX_op_shl_i64:
50c5c4d1 298 return (uint64_t)x << (y & 63);
55c0975c
KB
299
300 case INDEX_op_shr_i32:
50c5c4d1 301 return (uint32_t)x >> (y & 31);
55c0975c 302
55c0975c 303 case INDEX_op_shr_i64:
50c5c4d1 304 return (uint64_t)x >> (y & 63);
55c0975c
KB
305
306 case INDEX_op_sar_i32:
50c5c4d1 307 return (int32_t)x >> (y & 31);
55c0975c 308
55c0975c 309 case INDEX_op_sar_i64:
50c5c4d1 310 return (int64_t)x >> (y & 63);
55c0975c
KB
311
312 case INDEX_op_rotr_i32:
50c5c4d1 313 return ror32(x, y & 31);
55c0975c 314
55c0975c 315 case INDEX_op_rotr_i64:
50c5c4d1 316 return ror64(x, y & 63);
55c0975c
KB
317
318 case INDEX_op_rotl_i32:
50c5c4d1 319 return rol32(x, y & 31);
55c0975c 320
55c0975c 321 case INDEX_op_rotl_i64:
50c5c4d1 322 return rol64(x, y & 63);
25c4d9cc
RH
323
324 CASE_OP_32_64(not):
a640f031 325 return ~x;
25c4d9cc 326
cb25c80a
RH
327 CASE_OP_32_64(neg):
328 return -x;
329
330 CASE_OP_32_64(andc):
331 return x & ~y;
332
333 CASE_OP_32_64(orc):
334 return x | ~y;
335
336 CASE_OP_32_64(eqv):
337 return ~(x ^ y);
338
339 CASE_OP_32_64(nand):
340 return ~(x & y);
341
342 CASE_OP_32_64(nor):
343 return ~(x | y);
344
0e28d006
RH
345 case INDEX_op_clz_i32:
346 return (uint32_t)x ? clz32(x) : y;
347
348 case INDEX_op_clz_i64:
349 return x ? clz64(x) : y;
350
351 case INDEX_op_ctz_i32:
352 return (uint32_t)x ? ctz32(x) : y;
353
354 case INDEX_op_ctz_i64:
355 return x ? ctz64(x) : y;
356
a768e4e9
RH
357 case INDEX_op_ctpop_i32:
358 return ctpop32(x);
359
360 case INDEX_op_ctpop_i64:
361 return ctpop64(x);
362
25c4d9cc 363 CASE_OP_32_64(ext8s):
a640f031 364 return (int8_t)x;
25c4d9cc
RH
365
366 CASE_OP_32_64(ext16s):
a640f031 367 return (int16_t)x;
25c4d9cc
RH
368
369 CASE_OP_32_64(ext8u):
a640f031 370 return (uint8_t)x;
25c4d9cc
RH
371
372 CASE_OP_32_64(ext16u):
a640f031
KB
373 return (uint16_t)x;
374
8bcb5c8f 375 case INDEX_op_ext_i32_i64:
a640f031
KB
376 case INDEX_op_ext32s_i64:
377 return (int32_t)x;
378
8bcb5c8f 379 case INDEX_op_extu_i32_i64:
609ad705 380 case INDEX_op_extrl_i64_i32:
a640f031
KB
381 case INDEX_op_ext32u_i64:
382 return (uint32_t)x;
a640f031 383
609ad705
RH
384 case INDEX_op_extrh_i64_i32:
385 return (uint64_t)x >> 32;
386
03271524
RH
387 case INDEX_op_muluh_i32:
388 return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
389 case INDEX_op_mulsh_i32:
390 return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
391
392 case INDEX_op_muluh_i64:
393 mulu64(&l64, &h64, x, y);
394 return h64;
395 case INDEX_op_mulsh_i64:
396 muls64(&l64, &h64, x, y);
397 return h64;
398
01547f7f
RH
399 case INDEX_op_div_i32:
400 /* Avoid crashing on divide by zero, otherwise undefined. */
401 return (int32_t)x / ((int32_t)y ? : 1);
402 case INDEX_op_divu_i32:
403 return (uint32_t)x / ((uint32_t)y ? : 1);
404 case INDEX_op_div_i64:
405 return (int64_t)x / ((int64_t)y ? : 1);
406 case INDEX_op_divu_i64:
407 return (uint64_t)x / ((uint64_t)y ? : 1);
408
409 case INDEX_op_rem_i32:
410 return (int32_t)x % ((int32_t)y ? : 1);
411 case INDEX_op_remu_i32:
412 return (uint32_t)x % ((uint32_t)y ? : 1);
413 case INDEX_op_rem_i64:
414 return (int64_t)x % ((int64_t)y ? : 1);
415 case INDEX_op_remu_i64:
416 return (uint64_t)x % ((uint64_t)y ? : 1);
417
53108fb5
KB
418 default:
419 fprintf(stderr,
420 "Unrecognized operation %d in do_constant_folding.\n", op);
421 tcg_abort();
422 }
423}
424
fe0de7aa 425static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
53108fb5
KB
426{
427 TCGArg res = do_constant_folding_2(op, x, y);
53108fb5 428 if (op_bits(op) == 32) {
29f3ff8d 429 res = (int32_t)res;
53108fb5 430 }
53108fb5
KB
431 return res;
432}
433
9519da7e
RH
434static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
435{
436 switch (c) {
437 case TCG_COND_EQ:
438 return x == y;
439 case TCG_COND_NE:
440 return x != y;
441 case TCG_COND_LT:
442 return (int32_t)x < (int32_t)y;
443 case TCG_COND_GE:
444 return (int32_t)x >= (int32_t)y;
445 case TCG_COND_LE:
446 return (int32_t)x <= (int32_t)y;
447 case TCG_COND_GT:
448 return (int32_t)x > (int32_t)y;
449 case TCG_COND_LTU:
450 return x < y;
451 case TCG_COND_GEU:
452 return x >= y;
453 case TCG_COND_LEU:
454 return x <= y;
455 case TCG_COND_GTU:
456 return x > y;
457 default:
458 tcg_abort();
459 }
460}
461
462static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
463{
464 switch (c) {
465 case TCG_COND_EQ:
466 return x == y;
467 case TCG_COND_NE:
468 return x != y;
469 case TCG_COND_LT:
470 return (int64_t)x < (int64_t)y;
471 case TCG_COND_GE:
472 return (int64_t)x >= (int64_t)y;
473 case TCG_COND_LE:
474 return (int64_t)x <= (int64_t)y;
475 case TCG_COND_GT:
476 return (int64_t)x > (int64_t)y;
477 case TCG_COND_LTU:
478 return x < y;
479 case TCG_COND_GEU:
480 return x >= y;
481 case TCG_COND_LEU:
482 return x <= y;
483 case TCG_COND_GTU:
484 return x > y;
485 default:
486 tcg_abort();
487 }
488}
489
490static bool do_constant_folding_cond_eq(TCGCond c)
491{
492 switch (c) {
493 case TCG_COND_GT:
494 case TCG_COND_LTU:
495 case TCG_COND_LT:
496 case TCG_COND_GTU:
497 case TCG_COND_NE:
498 return 0;
499 case TCG_COND_GE:
500 case TCG_COND_GEU:
501 case TCG_COND_LE:
502 case TCG_COND_LEU:
503 case TCG_COND_EQ:
504 return 1;
505 default:
506 tcg_abort();
507 }
508}
509
b336ceb6
AJ
510/* Return 2 if the condition can't be simplified, and the result
511 of the condition (0 or 1) if it can */
f8dd19e5
AJ
512static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
513 TCGArg y, TCGCond c)
514{
6349039d
RH
515 tcg_target_ulong xv = arg_info(x)->val;
516 tcg_target_ulong yv = arg_info(y)->val;
517 if (arg_is_const(x) && arg_is_const(y)) {
b336ceb6
AJ
518 switch (op_bits(op)) {
519 case 32:
6349039d 520 return do_constant_folding_cond_32(xv, yv, c);
b336ceb6 521 case 64:
6349039d 522 return do_constant_folding_cond_64(xv, yv, c);
0aed257f 523 default:
9519da7e 524 tcg_abort();
b336ceb6 525 }
6349039d 526 } else if (args_are_copies(x, y)) {
9519da7e 527 return do_constant_folding_cond_eq(c);
6349039d 528 } else if (arg_is_const(y) && yv == 0) {
b336ceb6 529 switch (c) {
f8dd19e5 530 case TCG_COND_LTU:
b336ceb6 531 return 0;
f8dd19e5 532 case TCG_COND_GEU:
b336ceb6
AJ
533 return 1;
534 default:
535 return 2;
f8dd19e5 536 }
f8dd19e5 537 }
550276ae 538 return 2;
f8dd19e5
AJ
539}
540
6c4382f8
RH
541/* Return 2 if the condition can't be simplified, and the result
542 of the condition (0 or 1) if it can */
543static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
544{
545 TCGArg al = p1[0], ah = p1[1];
546 TCGArg bl = p2[0], bh = p2[1];
547
6349039d
RH
548 if (arg_is_const(bl) && arg_is_const(bh)) {
549 tcg_target_ulong blv = arg_info(bl)->val;
550 tcg_target_ulong bhv = arg_info(bh)->val;
551 uint64_t b = deposit64(blv, 32, 32, bhv);
6c4382f8 552
6349039d
RH
553 if (arg_is_const(al) && arg_is_const(ah)) {
554 tcg_target_ulong alv = arg_info(al)->val;
555 tcg_target_ulong ahv = arg_info(ah)->val;
556 uint64_t a = deposit64(alv, 32, 32, ahv);
6c4382f8
RH
557 return do_constant_folding_cond_64(a, b, c);
558 }
559 if (b == 0) {
560 switch (c) {
561 case TCG_COND_LTU:
562 return 0;
563 case TCG_COND_GEU:
564 return 1;
565 default:
566 break;
567 }
568 }
569 }
6349039d 570 if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
6c4382f8
RH
571 return do_constant_folding_cond_eq(c);
572 }
573 return 2;
574}
575
24c9ae4e
RH
576static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
577{
578 TCGArg a1 = *p1, a2 = *p2;
579 int sum = 0;
6349039d
RH
580 sum += arg_is_const(a1);
581 sum -= arg_is_const(a2);
24c9ae4e
RH
582
583 /* Prefer the constant in second argument, and then the form
584 op a, a, b, which is better handled on non-RISC hosts. */
585 if (sum > 0 || (sum == 0 && dest == a2)) {
586 *p1 = a2;
587 *p2 = a1;
588 return true;
589 }
590 return false;
591}
592
0bfcb865
RH
593static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
594{
595 int sum = 0;
6349039d
RH
596 sum += arg_is_const(p1[0]);
597 sum += arg_is_const(p1[1]);
598 sum -= arg_is_const(p2[0]);
599 sum -= arg_is_const(p2[1]);
0bfcb865
RH
600 if (sum > 0) {
601 TCGArg t;
602 t = p1[0], p1[0] = p2[0], p2[0] = t;
603 t = p1[1], p1[1] = p2[1], p2[1] = t;
604 return true;
605 }
606 return false;
607}
608
22613af4 609/* Propagate constants and copies, fold constant expressions. */
36e60ef6 610void tcg_optimize(TCGContext *s)
8f2e8c07 611{
c45cb8bb 612 int oi, oi_next, nb_temps, nb_globals;
acd93701 613 TCGOp *prev_mb = NULL;
5d8f5363 614
22613af4
KB
615 /* Array VALS has an element for each temp.
616 If this temp holds a constant then its value is kept in VALS' element.
e590d4e6
AJ
617 If this temp is a copy of other ones then the other copies are
618 available through the doubly linked circular list. */
8f2e8c07
KB
619
620 nb_temps = s->nb_temps;
621 nb_globals = s->nb_globals;
d193a14a 622 reset_all_temps(nb_temps);
8f2e8c07 623
dcb8e758 624 for (oi = s->gen_op_buf[0].next; oi != 0; oi = oi_next) {
24666baf 625 tcg_target_ulong mask, partmask, affected;
c45cb8bb 626 int nb_oargs, nb_iargs, i;
cf066674
RH
627 TCGArg tmp;
628
c45cb8bb 629 TCGOp * const op = &s->gen_op_buf[oi];
c45cb8bb
RH
630 TCGOpcode opc = op->opc;
631 const TCGOpDef *def = &tcg_op_defs[opc];
632
633 oi_next = op->next;
1208d7dd
AJ
634
635 /* Count the arguments, and initialize the temps that are
636 going to be used */
c45cb8bb
RH
637 if (opc == INDEX_op_call) {
638 nb_oargs = op->callo;
639 nb_iargs = op->calli;
1208d7dd 640 for (i = 0; i < nb_oargs + nb_iargs; i++) {
6349039d
RH
641 TCGTemp *ts = arg_temp(op->args[i]);
642 if (ts) {
643 init_ts_info(ts);
1208d7dd
AJ
644 }
645 }
1ff8c541 646 } else {
cf066674
RH
647 nb_oargs = def->nb_oargs;
648 nb_iargs = def->nb_iargs;
1208d7dd 649 for (i = 0; i < nb_oargs + nb_iargs; i++) {
6349039d 650 init_arg_info(op->args[i]);
1208d7dd 651 }
cf066674
RH
652 }
653
654 /* Do copy propagation */
655 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
6349039d
RH
656 TCGTemp *ts = arg_temp(op->args[i]);
657 if (ts && ts_is_copy(ts)) {
658 op->args[i] = temp_arg(find_better_copy(s, ts));
22613af4
KB
659 }
660 }
661
53108fb5 662 /* For commutative operations make constant second argument */
c45cb8bb 663 switch (opc) {
53108fb5
KB
664 CASE_OP_32_64(add):
665 CASE_OP_32_64(mul):
9a81090b
KB
666 CASE_OP_32_64(and):
667 CASE_OP_32_64(or):
668 CASE_OP_32_64(xor):
cb25c80a
RH
669 CASE_OP_32_64(eqv):
670 CASE_OP_32_64(nand):
671 CASE_OP_32_64(nor):
03271524
RH
672 CASE_OP_32_64(muluh):
673 CASE_OP_32_64(mulsh):
acd93701 674 swap_commutative(op->args[0], &op->args[1], &op->args[2]);
53108fb5 675 break;
65a7cce1 676 CASE_OP_32_64(brcond):
acd93701
RH
677 if (swap_commutative(-1, &op->args[0], &op->args[1])) {
678 op->args[2] = tcg_swap_cond(op->args[2]);
65a7cce1
AJ
679 }
680 break;
681 CASE_OP_32_64(setcond):
acd93701
RH
682 if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
683 op->args[3] = tcg_swap_cond(op->args[3]);
65a7cce1
AJ
684 }
685 break;
fa01a208 686 CASE_OP_32_64(movcond):
acd93701
RH
687 if (swap_commutative(-1, &op->args[1], &op->args[2])) {
688 op->args[5] = tcg_swap_cond(op->args[5]);
5d8f5363
RH
689 }
690 /* For movcond, we canonicalize the "false" input reg to match
691 the destination reg so that the tcg backend can implement
692 a "move if true" operation. */
acd93701
RH
693 if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
694 op->args[5] = tcg_invert_cond(op->args[5]);
fa01a208 695 }
1e484e61 696 break;
d7156f7c 697 CASE_OP_32_64(add2):
acd93701
RH
698 swap_commutative(op->args[0], &op->args[2], &op->args[4]);
699 swap_commutative(op->args[1], &op->args[3], &op->args[5]);
1e484e61 700 break;
d7156f7c 701 CASE_OP_32_64(mulu2):
4d3203fd 702 CASE_OP_32_64(muls2):
acd93701 703 swap_commutative(op->args[0], &op->args[2], &op->args[3]);
1414968a 704 break;
0bfcb865 705 case INDEX_op_brcond2_i32:
acd93701
RH
706 if (swap_commutative2(&op->args[0], &op->args[2])) {
707 op->args[4] = tcg_swap_cond(op->args[4]);
0bfcb865
RH
708 }
709 break;
710 case INDEX_op_setcond2_i32:
acd93701
RH
711 if (swap_commutative2(&op->args[1], &op->args[3])) {
712 op->args[5] = tcg_swap_cond(op->args[5]);
0bfcb865
RH
713 }
714 break;
53108fb5
KB
715 default:
716 break;
717 }
718
2d497542
RH
719 /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
720 and "sub r, 0, a => neg r, a" case. */
c45cb8bb 721 switch (opc) {
01ee5282
AJ
722 CASE_OP_32_64(shl):
723 CASE_OP_32_64(shr):
724 CASE_OP_32_64(sar):
725 CASE_OP_32_64(rotl):
726 CASE_OP_32_64(rotr):
6349039d
RH
727 if (arg_is_const(op->args[1])
728 && arg_info(op->args[1])->val == 0) {
acd93701 729 tcg_opt_gen_movi(s, op, op->args[0], 0);
01ee5282
AJ
730 continue;
731 }
732 break;
2d497542
RH
733 CASE_OP_32_64(sub):
734 {
735 TCGOpcode neg_op;
736 bool have_neg;
737
6349039d 738 if (arg_is_const(op->args[2])) {
2d497542
RH
739 /* Proceed with possible constant folding. */
740 break;
741 }
c45cb8bb 742 if (opc == INDEX_op_sub_i32) {
2d497542
RH
743 neg_op = INDEX_op_neg_i32;
744 have_neg = TCG_TARGET_HAS_neg_i32;
745 } else {
746 neg_op = INDEX_op_neg_i64;
747 have_neg = TCG_TARGET_HAS_neg_i64;
748 }
749 if (!have_neg) {
750 break;
751 }
6349039d
RH
752 if (arg_is_const(op->args[1])
753 && arg_info(op->args[1])->val == 0) {
c45cb8bb 754 op->opc = neg_op;
acd93701
RH
755 reset_temp(op->args[0]);
756 op->args[1] = op->args[2];
2d497542
RH
757 continue;
758 }
759 }
760 break;
e201b564
RH
761 CASE_OP_32_64(xor):
762 CASE_OP_32_64(nand):
6349039d
RH
763 if (!arg_is_const(op->args[1])
764 && arg_is_const(op->args[2])
765 && arg_info(op->args[2])->val == -1) {
e201b564
RH
766 i = 1;
767 goto try_not;
768 }
769 break;
770 CASE_OP_32_64(nor):
6349039d
RH
771 if (!arg_is_const(op->args[1])
772 && arg_is_const(op->args[2])
773 && arg_info(op->args[2])->val == 0) {
e201b564
RH
774 i = 1;
775 goto try_not;
776 }
777 break;
778 CASE_OP_32_64(andc):
6349039d
RH
779 if (!arg_is_const(op->args[2])
780 && arg_is_const(op->args[1])
781 && arg_info(op->args[1])->val == -1) {
e201b564
RH
782 i = 2;
783 goto try_not;
784 }
785 break;
786 CASE_OP_32_64(orc):
787 CASE_OP_32_64(eqv):
6349039d
RH
788 if (!arg_is_const(op->args[2])
789 && arg_is_const(op->args[1])
790 && arg_info(op->args[1])->val == 0) {
e201b564
RH
791 i = 2;
792 goto try_not;
793 }
794 break;
795 try_not:
796 {
797 TCGOpcode not_op;
798 bool have_not;
799
800 if (def->flags & TCG_OPF_64BIT) {
801 not_op = INDEX_op_not_i64;
802 have_not = TCG_TARGET_HAS_not_i64;
803 } else {
804 not_op = INDEX_op_not_i32;
805 have_not = TCG_TARGET_HAS_not_i32;
806 }
807 if (!have_not) {
808 break;
809 }
c45cb8bb 810 op->opc = not_op;
acd93701
RH
811 reset_temp(op->args[0]);
812 op->args[1] = op->args[i];
e201b564
RH
813 continue;
814 }
01ee5282
AJ
815 default:
816 break;
817 }
818
464a1441 819 /* Simplify expression for "op r, a, const => mov r, a" cases */
c45cb8bb 820 switch (opc) {
53108fb5
KB
821 CASE_OP_32_64(add):
822 CASE_OP_32_64(sub):
55c0975c
KB
823 CASE_OP_32_64(shl):
824 CASE_OP_32_64(shr):
825 CASE_OP_32_64(sar):
25c4d9cc
RH
826 CASE_OP_32_64(rotl):
827 CASE_OP_32_64(rotr):
38ee188b
AJ
828 CASE_OP_32_64(or):
829 CASE_OP_32_64(xor):
464a1441 830 CASE_OP_32_64(andc):
6349039d
RH
831 if (!arg_is_const(op->args[1])
832 && arg_is_const(op->args[2])
833 && arg_info(op->args[2])->val == 0) {
acd93701 834 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
97a79eb7 835 continue;
53108fb5
KB
836 }
837 break;
464a1441
RH
838 CASE_OP_32_64(and):
839 CASE_OP_32_64(orc):
840 CASE_OP_32_64(eqv):
6349039d
RH
841 if (!arg_is_const(op->args[1])
842 && arg_is_const(op->args[2])
843 && arg_info(op->args[2])->val == -1) {
acd93701 844 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
97a79eb7 845 continue;
464a1441
RH
846 }
847 break;
56e49438
AJ
848 default:
849 break;
850 }
851
3031244b
AJ
852 /* Simplify using known-zero bits. Currently only ops with a single
853 output argument is supported. */
3a9d8b17 854 mask = -1;
633f6502 855 affected = -1;
c45cb8bb 856 switch (opc) {
3a9d8b17 857 CASE_OP_32_64(ext8s):
6349039d 858 if ((arg_info(op->args[1])->mask & 0x80) != 0) {
3a9d8b17
PB
859 break;
860 }
861 CASE_OP_32_64(ext8u):
862 mask = 0xff;
863 goto and_const;
864 CASE_OP_32_64(ext16s):
6349039d 865 if ((arg_info(op->args[1])->mask & 0x8000) != 0) {
3a9d8b17
PB
866 break;
867 }
868 CASE_OP_32_64(ext16u):
869 mask = 0xffff;
870 goto and_const;
871 case INDEX_op_ext32s_i64:
6349039d 872 if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
3a9d8b17
PB
873 break;
874 }
875 case INDEX_op_ext32u_i64:
876 mask = 0xffffffffU;
877 goto and_const;
878
879 CASE_OP_32_64(and):
6349039d
RH
880 mask = arg_info(op->args[2])->mask;
881 if (arg_is_const(op->args[2])) {
3a9d8b17 882 and_const:
6349039d 883 affected = arg_info(op->args[1])->mask & ~mask;
3a9d8b17 884 }
6349039d 885 mask = arg_info(op->args[1])->mask & mask;
3a9d8b17
PB
886 break;
887
8bcb5c8f 888 case INDEX_op_ext_i32_i64:
6349039d 889 if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
8bcb5c8f
AJ
890 break;
891 }
892 case INDEX_op_extu_i32_i64:
893 /* We do not compute affected as it is a size changing op. */
6349039d 894 mask = (uint32_t)arg_info(op->args[1])->mask;
8bcb5c8f
AJ
895 break;
896
23ec69ed
RH
897 CASE_OP_32_64(andc):
898 /* Known-zeros does not imply known-ones. Therefore unless
acd93701 899 op->args[2] is constant, we can't infer anything from it. */
6349039d
RH
900 if (arg_is_const(op->args[2])) {
901 mask = ~arg_info(op->args[2])->mask;
23ec69ed
RH
902 goto and_const;
903 }
6349039d
RH
904 /* But we certainly know nothing outside args[1] may be set. */
905 mask = arg_info(op->args[1])->mask;
23ec69ed
RH
906 break;
907
e46b225a 908 case INDEX_op_sar_i32:
6349039d
RH
909 if (arg_is_const(op->args[2])) {
910 tmp = arg_info(op->args[2])->val & 31;
911 mask = (int32_t)arg_info(op->args[1])->mask >> tmp;
e46b225a
AJ
912 }
913 break;
914 case INDEX_op_sar_i64:
6349039d
RH
915 if (arg_is_const(op->args[2])) {
916 tmp = arg_info(op->args[2])->val & 63;
917 mask = (int64_t)arg_info(op->args[1])->mask >> tmp;
3a9d8b17
PB
918 }
919 break;
920
e46b225a 921 case INDEX_op_shr_i32:
6349039d
RH
922 if (arg_is_const(op->args[2])) {
923 tmp = arg_info(op->args[2])->val & 31;
924 mask = (uint32_t)arg_info(op->args[1])->mask >> tmp;
e46b225a
AJ
925 }
926 break;
927 case INDEX_op_shr_i64:
6349039d
RH
928 if (arg_is_const(op->args[2])) {
929 tmp = arg_info(op->args[2])->val & 63;
930 mask = (uint64_t)arg_info(op->args[1])->mask >> tmp;
3a9d8b17
PB
931 }
932 break;
933
609ad705 934 case INDEX_op_extrl_i64_i32:
6349039d 935 mask = (uint32_t)arg_info(op->args[1])->mask;
609ad705
RH
936 break;
937 case INDEX_op_extrh_i64_i32:
6349039d 938 mask = (uint64_t)arg_info(op->args[1])->mask >> 32;
4bb7a41e
RH
939 break;
940
3a9d8b17 941 CASE_OP_32_64(shl):
6349039d
RH
942 if (arg_is_const(op->args[2])) {
943 tmp = arg_info(op->args[2])->val & (TCG_TARGET_REG_BITS - 1);
944 mask = arg_info(op->args[1])->mask << tmp;
3a9d8b17
PB
945 }
946 break;
947
948 CASE_OP_32_64(neg):
949 /* Set to 1 all bits to the left of the rightmost. */
6349039d
RH
950 mask = -(arg_info(op->args[1])->mask
951 & -arg_info(op->args[1])->mask);
3a9d8b17
PB
952 break;
953
954 CASE_OP_32_64(deposit):
6349039d
RH
955 mask = deposit64(arg_info(op->args[1])->mask,
956 op->args[3], op->args[4],
957 arg_info(op->args[2])->mask);
3a9d8b17
PB
958 break;
959
7ec8bab3 960 CASE_OP_32_64(extract):
6349039d
RH
961 mask = extract64(arg_info(op->args[1])->mask,
962 op->args[2], op->args[3]);
acd93701 963 if (op->args[2] == 0) {
6349039d 964 affected = arg_info(op->args[1])->mask & ~mask;
7ec8bab3
RH
965 }
966 break;
967 CASE_OP_32_64(sextract):
6349039d 968 mask = sextract64(arg_info(op->args[1])->mask,
acd93701
RH
969 op->args[2], op->args[3]);
970 if (op->args[2] == 0 && (tcg_target_long)mask >= 0) {
6349039d 971 affected = arg_info(op->args[1])->mask & ~mask;
7ec8bab3
RH
972 }
973 break;
974
3a9d8b17
PB
975 CASE_OP_32_64(or):
976 CASE_OP_32_64(xor):
6349039d 977 mask = arg_info(op->args[1])->mask | arg_info(op->args[2])->mask;
3a9d8b17
PB
978 break;
979
0e28d006
RH
980 case INDEX_op_clz_i32:
981 case INDEX_op_ctz_i32:
6349039d 982 mask = arg_info(op->args[2])->mask | 31;
0e28d006
RH
983 break;
984
985 case INDEX_op_clz_i64:
986 case INDEX_op_ctz_i64:
6349039d 987 mask = arg_info(op->args[2])->mask | 63;
0e28d006
RH
988 break;
989
a768e4e9
RH
990 case INDEX_op_ctpop_i32:
991 mask = 32 | 31;
992 break;
993 case INDEX_op_ctpop_i64:
994 mask = 64 | 63;
995 break;
996
3a9d8b17 997 CASE_OP_32_64(setcond):
a763551a 998 case INDEX_op_setcond2_i32:
3a9d8b17
PB
999 mask = 1;
1000 break;
1001
1002 CASE_OP_32_64(movcond):
6349039d 1003 mask = arg_info(op->args[3])->mask | arg_info(op->args[4])->mask;
3a9d8b17
PB
1004 break;
1005
c8d70272 1006 CASE_OP_32_64(ld8u):
c8d70272
AJ
1007 mask = 0xff;
1008 break;
1009 CASE_OP_32_64(ld16u):
c8d70272
AJ
1010 mask = 0xffff;
1011 break;
1012 case INDEX_op_ld32u_i64:
c8d70272
AJ
1013 mask = 0xffffffffu;
1014 break;
1015
1016 CASE_OP_32_64(qemu_ld):
1017 {
acd93701 1018 TCGMemOpIdx oi = op->args[nb_oargs + nb_iargs];
59227d5d 1019 TCGMemOp mop = get_memop(oi);
c8d70272
AJ
1020 if (!(mop & MO_SIGN)) {
1021 mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
1022 }
1023 }
1024 break;
1025
3a9d8b17
PB
1026 default:
1027 break;
1028 }
1029
bc8d688f
RH
1030 /* 32-bit ops generate 32-bit results. For the result is zero test
1031 below, we can ignore high bits, but for further optimizations we
1032 need to record that the high bits contain garbage. */
24666baf 1033 partmask = mask;
bc8d688f 1034 if (!(def->flags & TCG_OPF_64BIT)) {
24666baf
RH
1035 mask |= ~(tcg_target_ulong)0xffffffffu;
1036 partmask &= 0xffffffffu;
1037 affected &= 0xffffffffu;
f096dc96
AJ
1038 }
1039
24666baf 1040 if (partmask == 0) {
eabb7b91 1041 tcg_debug_assert(nb_oargs == 1);
acd93701 1042 tcg_opt_gen_movi(s, op, op->args[0], 0);
633f6502
PB
1043 continue;
1044 }
1045 if (affected == 0) {
eabb7b91 1046 tcg_debug_assert(nb_oargs == 1);
acd93701 1047 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
633f6502
PB
1048 continue;
1049 }
1050
56e49438 1051 /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
c45cb8bb 1052 switch (opc) {
61251c0c 1053 CASE_OP_32_64(and):
53108fb5 1054 CASE_OP_32_64(mul):
03271524
RH
1055 CASE_OP_32_64(muluh):
1056 CASE_OP_32_64(mulsh):
6349039d
RH
1057 if (arg_is_const(op->args[2])
1058 && arg_info(op->args[2])->val == 0) {
acd93701 1059 tcg_opt_gen_movi(s, op, op->args[0], 0);
53108fb5
KB
1060 continue;
1061 }
1062 break;
56e49438
AJ
1063 default:
1064 break;
1065 }
1066
1067 /* Simplify expression for "op r, a, a => mov r, a" cases */
c45cb8bb 1068 switch (opc) {
9a81090b
KB
1069 CASE_OP_32_64(or):
1070 CASE_OP_32_64(and):
6349039d 1071 if (args_are_copies(op->args[1], op->args[2])) {
acd93701 1072 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
9a81090b
KB
1073 continue;
1074 }
1075 break;
fe0de7aa
BS
1076 default:
1077 break;
53108fb5
KB
1078 }
1079
3c94193e 1080 /* Simplify expression for "op r, a, a => movi r, 0" cases */
c45cb8bb 1081 switch (opc) {
e64e958e 1082 CASE_OP_32_64(andc):
3c94193e
AJ
1083 CASE_OP_32_64(sub):
1084 CASE_OP_32_64(xor):
6349039d 1085 if (args_are_copies(op->args[1], op->args[2])) {
acd93701 1086 tcg_opt_gen_movi(s, op, op->args[0], 0);
3c94193e
AJ
1087 continue;
1088 }
1089 break;
1090 default:
1091 break;
1092 }
1093
22613af4
KB
1094 /* Propagate constants through copy operations and do constant
1095 folding. Constants will be substituted to arguments by register
1096 allocator where needed and possible. Also detect copies. */
c45cb8bb 1097 switch (opc) {
22613af4 1098 CASE_OP_32_64(mov):
acd93701 1099 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
97a79eb7 1100 break;
22613af4 1101 CASE_OP_32_64(movi):
acd93701 1102 tcg_opt_gen_movi(s, op, op->args[0], op->args[1]);
22613af4 1103 break;
6e14e91b 1104
a640f031 1105 CASE_OP_32_64(not):
cb25c80a 1106 CASE_OP_32_64(neg):
25c4d9cc
RH
1107 CASE_OP_32_64(ext8s):
1108 CASE_OP_32_64(ext8u):
1109 CASE_OP_32_64(ext16s):
1110 CASE_OP_32_64(ext16u):
a768e4e9 1111 CASE_OP_32_64(ctpop):
a640f031
KB
1112 case INDEX_op_ext32s_i64:
1113 case INDEX_op_ext32u_i64:
8bcb5c8f
AJ
1114 case INDEX_op_ext_i32_i64:
1115 case INDEX_op_extu_i32_i64:
609ad705
RH
1116 case INDEX_op_extrl_i64_i32:
1117 case INDEX_op_extrh_i64_i32:
6349039d
RH
1118 if (arg_is_const(op->args[1])) {
1119 tmp = do_constant_folding(opc, arg_info(op->args[1])->val, 0);
acd93701 1120 tcg_opt_gen_movi(s, op, op->args[0], tmp);
6e14e91b 1121 break;
a640f031 1122 }
6e14e91b
RH
1123 goto do_default;
1124
53108fb5
KB
1125 CASE_OP_32_64(add):
1126 CASE_OP_32_64(sub):
1127 CASE_OP_32_64(mul):
9a81090b
KB
1128 CASE_OP_32_64(or):
1129 CASE_OP_32_64(and):
1130 CASE_OP_32_64(xor):
55c0975c
KB
1131 CASE_OP_32_64(shl):
1132 CASE_OP_32_64(shr):
1133 CASE_OP_32_64(sar):
25c4d9cc
RH
1134 CASE_OP_32_64(rotl):
1135 CASE_OP_32_64(rotr):
cb25c80a
RH
1136 CASE_OP_32_64(andc):
1137 CASE_OP_32_64(orc):
1138 CASE_OP_32_64(eqv):
1139 CASE_OP_32_64(nand):
1140 CASE_OP_32_64(nor):
03271524
RH
1141 CASE_OP_32_64(muluh):
1142 CASE_OP_32_64(mulsh):
01547f7f
RH
1143 CASE_OP_32_64(div):
1144 CASE_OP_32_64(divu):
1145 CASE_OP_32_64(rem):
1146 CASE_OP_32_64(remu):
6349039d
RH
1147 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1148 tmp = do_constant_folding(opc, arg_info(op->args[1])->val,
1149 arg_info(op->args[2])->val);
acd93701 1150 tcg_opt_gen_movi(s, op, op->args[0], tmp);
6e14e91b 1151 break;
53108fb5 1152 }
6e14e91b
RH
1153 goto do_default;
1154
0e28d006
RH
1155 CASE_OP_32_64(clz):
1156 CASE_OP_32_64(ctz):
6349039d
RH
1157 if (arg_is_const(op->args[1])) {
1158 TCGArg v = arg_info(op->args[1])->val;
0e28d006
RH
1159 if (v != 0) {
1160 tmp = do_constant_folding(opc, v, 0);
acd93701 1161 tcg_opt_gen_movi(s, op, op->args[0], tmp);
0e28d006 1162 } else {
acd93701 1163 tcg_opt_gen_mov(s, op, op->args[0], op->args[2]);
0e28d006
RH
1164 }
1165 break;
1166 }
1167 goto do_default;
1168
7ef55fc9 1169 CASE_OP_32_64(deposit):
6349039d
RH
1170 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
1171 tmp = deposit64(arg_info(op->args[1])->val,
1172 op->args[3], op->args[4],
1173 arg_info(op->args[2])->val);
acd93701 1174 tcg_opt_gen_movi(s, op, op->args[0], tmp);
6e14e91b 1175 break;
7ef55fc9 1176 }
6e14e91b
RH
1177 goto do_default;
1178
7ec8bab3 1179 CASE_OP_32_64(extract):
6349039d
RH
1180 if (arg_is_const(op->args[1])) {
1181 tmp = extract64(arg_info(op->args[1])->val,
acd93701
RH
1182 op->args[2], op->args[3]);
1183 tcg_opt_gen_movi(s, op, op->args[0], tmp);
7ec8bab3
RH
1184 break;
1185 }
1186 goto do_default;
1187
1188 CASE_OP_32_64(sextract):
6349039d
RH
1189 if (arg_is_const(op->args[1])) {
1190 tmp = sextract64(arg_info(op->args[1])->val,
acd93701
RH
1191 op->args[2], op->args[3]);
1192 tcg_opt_gen_movi(s, op, op->args[0], tmp);
7ec8bab3
RH
1193 break;
1194 }
1195 goto do_default;
1196
f8dd19e5 1197 CASE_OP_32_64(setcond):
acd93701
RH
1198 tmp = do_constant_folding_cond(opc, op->args[1],
1199 op->args[2], op->args[3]);
b336ceb6 1200 if (tmp != 2) {
acd93701 1201 tcg_opt_gen_movi(s, op, op->args[0], tmp);
6e14e91b 1202 break;
f8dd19e5 1203 }
6e14e91b
RH
1204 goto do_default;
1205
fbeaa26c 1206 CASE_OP_32_64(brcond):
acd93701
RH
1207 tmp = do_constant_folding_cond(opc, op->args[0],
1208 op->args[1], op->args[2]);
b336ceb6
AJ
1209 if (tmp != 2) {
1210 if (tmp) {
d193a14a 1211 reset_all_temps(nb_temps);
c45cb8bb 1212 op->opc = INDEX_op_br;
acd93701 1213 op->args[0] = op->args[3];
fbeaa26c 1214 } else {
0c627cdc 1215 tcg_op_remove(s, op);
fbeaa26c 1216 }
6e14e91b 1217 break;
fbeaa26c 1218 }
6e14e91b
RH
1219 goto do_default;
1220
fa01a208 1221 CASE_OP_32_64(movcond):
acd93701
RH
1222 tmp = do_constant_folding_cond(opc, op->args[1],
1223 op->args[2], op->args[5]);
b336ceb6 1224 if (tmp != 2) {
acd93701 1225 tcg_opt_gen_mov(s, op, op->args[0], op->args[4-tmp]);
6e14e91b 1226 break;
fa01a208 1227 }
6349039d
RH
1228 if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
1229 tcg_target_ulong tv = arg_info(op->args[3])->val;
1230 tcg_target_ulong fv = arg_info(op->args[4])->val;
acd93701 1231 TCGCond cond = op->args[5];
333b21b8
RH
1232 if (fv == 1 && tv == 0) {
1233 cond = tcg_invert_cond(cond);
1234 } else if (!(tv == 1 && fv == 0)) {
1235 goto do_default;
1236 }
acd93701 1237 op->args[3] = cond;
333b21b8
RH
1238 op->opc = opc = (opc == INDEX_op_movcond_i32
1239 ? INDEX_op_setcond_i32
1240 : INDEX_op_setcond_i64);
1241 nb_iargs = 2;
1242 }
6e14e91b 1243 goto do_default;
212c328d
RH
1244
1245 case INDEX_op_add2_i32:
1246 case INDEX_op_sub2_i32:
6349039d
RH
1247 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])
1248 && arg_is_const(op->args[4]) && arg_is_const(op->args[5])) {
1249 uint32_t al = arg_info(op->args[2])->val;
1250 uint32_t ah = arg_info(op->args[3])->val;
1251 uint32_t bl = arg_info(op->args[4])->val;
1252 uint32_t bh = arg_info(op->args[5])->val;
212c328d
RH
1253 uint64_t a = ((uint64_t)ah << 32) | al;
1254 uint64_t b = ((uint64_t)bh << 32) | bl;
1255 TCGArg rl, rh;
5a18407f 1256 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
212c328d 1257
c45cb8bb 1258 if (opc == INDEX_op_add2_i32) {
212c328d
RH
1259 a += b;
1260 } else {
1261 a -= b;
1262 }
1263
acd93701
RH
1264 rl = op->args[0];
1265 rh = op->args[1];
1266 tcg_opt_gen_movi(s, op, rl, (int32_t)a);
1267 tcg_opt_gen_movi(s, op2, rh, (int32_t)(a >> 32));
c45cb8bb
RH
1268
1269 /* We've done all we need to do with the movi. Skip it. */
1270 oi_next = op2->next;
212c328d
RH
1271 break;
1272 }
1273 goto do_default;
1414968a
RH
1274
1275 case INDEX_op_mulu2_i32:
6349039d
RH
1276 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) {
1277 uint32_t a = arg_info(op->args[2])->val;
1278 uint32_t b = arg_info(op->args[3])->val;
1414968a
RH
1279 uint64_t r = (uint64_t)a * b;
1280 TCGArg rl, rh;
5a18407f 1281 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32, 2);
1414968a 1282
acd93701
RH
1283 rl = op->args[0];
1284 rh = op->args[1];
1285 tcg_opt_gen_movi(s, op, rl, (int32_t)r);
1286 tcg_opt_gen_movi(s, op2, rh, (int32_t)(r >> 32));
c45cb8bb
RH
1287
1288 /* We've done all we need to do with the movi. Skip it. */
1289 oi_next = op2->next;
1414968a
RH
1290 break;
1291 }
1292 goto do_default;
6e14e91b 1293
bc1473ef 1294 case INDEX_op_brcond2_i32:
acd93701
RH
1295 tmp = do_constant_folding_cond2(&op->args[0], &op->args[2],
1296 op->args[4]);
6c4382f8
RH
1297 if (tmp != 2) {
1298 if (tmp) {
a763551a 1299 do_brcond_true:
d193a14a 1300 reset_all_temps(nb_temps);
c45cb8bb 1301 op->opc = INDEX_op_br;
acd93701 1302 op->args[0] = op->args[5];
6c4382f8 1303 } else {
a763551a 1304 do_brcond_false:
0c627cdc 1305 tcg_op_remove(s, op);
6c4382f8 1306 }
acd93701
RH
1307 } else if ((op->args[4] == TCG_COND_LT
1308 || op->args[4] == TCG_COND_GE)
6349039d
RH
1309 && arg_is_const(op->args[2])
1310 && arg_info(op->args[2])->val == 0
1311 && arg_is_const(op->args[3])
1312 && arg_info(op->args[3])->val == 0) {
6c4382f8
RH
1313 /* Simplify LT/GE comparisons vs zero to a single compare
1314 vs the high word of the input. */
a763551a 1315 do_brcond_high:
d193a14a 1316 reset_all_temps(nb_temps);
c45cb8bb 1317 op->opc = INDEX_op_brcond_i32;
acd93701
RH
1318 op->args[0] = op->args[1];
1319 op->args[1] = op->args[3];
1320 op->args[2] = op->args[4];
1321 op->args[3] = op->args[5];
1322 } else if (op->args[4] == TCG_COND_EQ) {
a763551a
RH
1323 /* Simplify EQ comparisons where one of the pairs
1324 can be simplified. */
1325 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
acd93701
RH
1326 op->args[0], op->args[2],
1327 TCG_COND_EQ);
a763551a
RH
1328 if (tmp == 0) {
1329 goto do_brcond_false;
1330 } else if (tmp == 1) {
1331 goto do_brcond_high;
1332 }
1333 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
acd93701
RH
1334 op->args[1], op->args[3],
1335 TCG_COND_EQ);
a763551a
RH
1336 if (tmp == 0) {
1337 goto do_brcond_false;
1338 } else if (tmp != 1) {
1339 goto do_default;
1340 }
1341 do_brcond_low:
1342 reset_all_temps(nb_temps);
c45cb8bb 1343 op->opc = INDEX_op_brcond_i32;
acd93701
RH
1344 op->args[1] = op->args[2];
1345 op->args[2] = op->args[4];
1346 op->args[3] = op->args[5];
1347 } else if (op->args[4] == TCG_COND_NE) {
a763551a
RH
1348 /* Simplify NE comparisons where one of the pairs
1349 can be simplified. */
1350 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
acd93701
RH
1351 op->args[0], op->args[2],
1352 TCG_COND_NE);
a763551a
RH
1353 if (tmp == 0) {
1354 goto do_brcond_high;
1355 } else if (tmp == 1) {
1356 goto do_brcond_true;
1357 }
1358 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
acd93701
RH
1359 op->args[1], op->args[3],
1360 TCG_COND_NE);
a763551a
RH
1361 if (tmp == 0) {
1362 goto do_brcond_low;
1363 } else if (tmp == 1) {
1364 goto do_brcond_true;
1365 }
1366 goto do_default;
6c4382f8
RH
1367 } else {
1368 goto do_default;
bc1473ef 1369 }
6c4382f8 1370 break;
bc1473ef
RH
1371
1372 case INDEX_op_setcond2_i32:
acd93701
RH
1373 tmp = do_constant_folding_cond2(&op->args[1], &op->args[3],
1374 op->args[5]);
6c4382f8 1375 if (tmp != 2) {
a763551a 1376 do_setcond_const:
acd93701
RH
1377 tcg_opt_gen_movi(s, op, op->args[0], tmp);
1378 } else if ((op->args[5] == TCG_COND_LT
1379 || op->args[5] == TCG_COND_GE)
6349039d
RH
1380 && arg_is_const(op->args[3])
1381 && arg_info(op->args[3])->val == 0
1382 && arg_is_const(op->args[4])
1383 && arg_info(op->args[4])->val == 0) {
6c4382f8
RH
1384 /* Simplify LT/GE comparisons vs zero to a single compare
1385 vs the high word of the input. */
a763551a 1386 do_setcond_high:
acd93701 1387 reset_temp(op->args[0]);
6349039d 1388 arg_info(op->args[0])->mask = 1;
c45cb8bb 1389 op->opc = INDEX_op_setcond_i32;
acd93701
RH
1390 op->args[1] = op->args[2];
1391 op->args[2] = op->args[4];
1392 op->args[3] = op->args[5];
1393 } else if (op->args[5] == TCG_COND_EQ) {
a763551a
RH
1394 /* Simplify EQ comparisons where one of the pairs
1395 can be simplified. */
1396 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
acd93701
RH
1397 op->args[1], op->args[3],
1398 TCG_COND_EQ);
a763551a
RH
1399 if (tmp == 0) {
1400 goto do_setcond_const;
1401 } else if (tmp == 1) {
1402 goto do_setcond_high;
1403 }
1404 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
acd93701
RH
1405 op->args[2], op->args[4],
1406 TCG_COND_EQ);
a763551a
RH
1407 if (tmp == 0) {
1408 goto do_setcond_high;
1409 } else if (tmp != 1) {
1410 goto do_default;
1411 }
1412 do_setcond_low:
acd93701 1413 reset_temp(op->args[0]);
6349039d 1414 arg_info(op->args[0])->mask = 1;
c45cb8bb 1415 op->opc = INDEX_op_setcond_i32;
acd93701
RH
1416 op->args[2] = op->args[3];
1417 op->args[3] = op->args[5];
1418 } else if (op->args[5] == TCG_COND_NE) {
a763551a
RH
1419 /* Simplify NE comparisons where one of the pairs
1420 can be simplified. */
1421 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
acd93701
RH
1422 op->args[1], op->args[3],
1423 TCG_COND_NE);
a763551a
RH
1424 if (tmp == 0) {
1425 goto do_setcond_high;
1426 } else if (tmp == 1) {
1427 goto do_setcond_const;
1428 }
1429 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
acd93701
RH
1430 op->args[2], op->args[4],
1431 TCG_COND_NE);
a763551a
RH
1432 if (tmp == 0) {
1433 goto do_setcond_low;
1434 } else if (tmp == 1) {
1435 goto do_setcond_const;
1436 }
1437 goto do_default;
6c4382f8
RH
1438 } else {
1439 goto do_default;
bc1473ef 1440 }
6c4382f8 1441 break;
bc1473ef 1442
8f2e8c07 1443 case INDEX_op_call:
acd93701 1444 if (!(op->args[nb_oargs + nb_iargs + 1]
cf066674 1445 & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
22613af4 1446 for (i = 0; i < nb_globals; i++) {
1208d7dd 1447 if (test_bit(i, temps_used.l)) {
6349039d 1448 reset_ts(&s->temps[i]);
1208d7dd 1449 }
22613af4
KB
1450 }
1451 }
cf066674 1452 goto do_reset_output;
6e14e91b 1453
8f2e8c07 1454 default:
6e14e91b
RH
1455 do_default:
1456 /* Default case: we know nothing about operation (or were unable
1457 to compute the operation result) so no propagation is done.
1458 We trash everything if the operation is the end of a basic
3a9d8b17
PB
1459 block, otherwise we only trash the output args. "mask" is
1460 the non-zero bits mask for the first output arg. */
a2550660 1461 if (def->flags & TCG_OPF_BB_END) {
d193a14a 1462 reset_all_temps(nb_temps);
a2550660 1463 } else {
cf066674
RH
1464 do_reset_output:
1465 for (i = 0; i < nb_oargs; i++) {
acd93701 1466 reset_temp(op->args[i]);
3031244b
AJ
1467 /* Save the corresponding known-zero bits mask for the
1468 first output argument (only one supported so far). */
1469 if (i == 0) {
6349039d 1470 arg_info(op->args[i])->mask = mask;
3031244b 1471 }
a2550660 1472 }
22613af4 1473 }
8f2e8c07
KB
1474 break;
1475 }
34f93921
PK
1476
1477 /* Eliminate duplicate and redundant fence instructions. */
acd93701 1478 if (prev_mb) {
34f93921
PK
1479 switch (opc) {
1480 case INDEX_op_mb:
1481 /* Merge two barriers of the same type into one,
1482 * or a weaker barrier into a stronger one,
1483 * or two weaker barriers into a stronger one.
1484 * mb X; mb Y => mb X|Y
1485 * mb; strl => mb; st
1486 * ldaq; mb => ld; mb
1487 * ldaq; strl => ld; mb; st
1488 * Other combinations are also merged into a strong
1489 * barrier. This is stricter than specified but for
1490 * the purposes of TCG is better than not optimizing.
1491 */
acd93701 1492 prev_mb->args[0] |= op->args[0];
34f93921
PK
1493 tcg_op_remove(s, op);
1494 break;
1495
1496 default:
1497 /* Opcodes that end the block stop the optimization. */
1498 if ((def->flags & TCG_OPF_BB_END) == 0) {
1499 break;
1500 }
1501 /* fallthru */
1502 case INDEX_op_qemu_ld_i32:
1503 case INDEX_op_qemu_ld_i64:
1504 case INDEX_op_qemu_st_i32:
1505 case INDEX_op_qemu_st_i64:
1506 case INDEX_op_call:
1507 /* Opcodes that touch guest memory stop the optimization. */
acd93701 1508 prev_mb = NULL;
34f93921
PK
1509 break;
1510 }
1511 } else if (opc == INDEX_op_mb) {
acd93701 1512 prev_mb = op;
34f93921 1513 }
8f2e8c07 1514 }
8f2e8c07 1515}