]> Git Repo - qemu.git/blob - tcg/optimize.c
tcg: Split out subroutines from do_constant_folding_cond
[qemu.git] / tcg / optimize.c
1 /*
2  * Optimizations for Tiny Code Generator for QEMU
3  *
4  * Copyright (c) 2010 Samsung Electronics.
5  * Contributed by Kirill Batuzov <[email protected]>
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
26 #include "config.h"
27
28 #include <stdlib.h>
29 #include <stdio.h>
30
31 #include "qemu-common.h"
32 #include "tcg-op.h"
33
34 #define CASE_OP_32_64(x)                        \
35         glue(glue(case INDEX_op_, x), _i32):    \
36         glue(glue(case INDEX_op_, x), _i64)
37
38 typedef enum {
39     TCG_TEMP_UNDEF = 0,
40     TCG_TEMP_CONST,
41     TCG_TEMP_COPY,
42 } tcg_temp_state;
43
44 struct tcg_temp_info {
45     tcg_temp_state state;
46     uint16_t prev_copy;
47     uint16_t next_copy;
48     tcg_target_ulong val;
49 };
50
51 static struct tcg_temp_info temps[TCG_MAX_TEMPS];
52
53 /* Reset TEMP's state to TCG_TEMP_UNDEF.  If TEMP only had one copy, remove
54    the copy flag from the left temp.  */
55 static void reset_temp(TCGArg temp)
56 {
57     if (temps[temp].state == TCG_TEMP_COPY) {
58         if (temps[temp].prev_copy == temps[temp].next_copy) {
59             temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF;
60         } else {
61             temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
62             temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
63         }
64     }
65     temps[temp].state = TCG_TEMP_UNDEF;
66 }
67
68 static int op_bits(TCGOpcode op)
69 {
70     const TCGOpDef *def = &tcg_op_defs[op];
71     return def->flags & TCG_OPF_64BIT ? 64 : 32;
72 }
73
74 static TCGOpcode op_to_movi(TCGOpcode op)
75 {
76     switch (op_bits(op)) {
77     case 32:
78         return INDEX_op_movi_i32;
79     case 64:
80         return INDEX_op_movi_i64;
81     default:
82         fprintf(stderr, "op_to_movi: unexpected return value of "
83                 "function op_bits.\n");
84         tcg_abort();
85     }
86 }
87
88 static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
89 {
90     TCGArg i;
91
92     /* If this is already a global, we can't do better. */
93     if (temp < s->nb_globals) {
94         return temp;
95     }
96
97     /* Search for a global first. */
98     for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
99         if (i < s->nb_globals) {
100             return i;
101         }
102     }
103
104     /* If it is a temp, search for a temp local. */
105     if (!s->temps[temp].temp_local) {
106         for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
107             if (s->temps[i].temp_local) {
108                 return i;
109             }
110         }
111     }
112
113     /* Failure to find a better representation, return the same temp. */
114     return temp;
115 }
116
117 static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
118 {
119     TCGArg i;
120
121     if (arg1 == arg2) {
122         return true;
123     }
124
125     if (temps[arg1].state != TCG_TEMP_COPY
126         || temps[arg2].state != TCG_TEMP_COPY) {
127         return false;
128     }
129
130     for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
131         if (i == arg2) {
132             return true;
133         }
134     }
135
136     return false;
137 }
138
139 static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
140                             TCGArg dst, TCGArg src)
141 {
142         reset_temp(dst);
143         assert(temps[src].state != TCG_TEMP_CONST);
144
145         if (s->temps[src].type == s->temps[dst].type) {
146             if (temps[src].state != TCG_TEMP_COPY) {
147                 temps[src].state = TCG_TEMP_COPY;
148                 temps[src].next_copy = src;
149                 temps[src].prev_copy = src;
150             }
151             temps[dst].state = TCG_TEMP_COPY;
152             temps[dst].next_copy = temps[src].next_copy;
153             temps[dst].prev_copy = src;
154             temps[temps[dst].next_copy].prev_copy = dst;
155             temps[src].next_copy = dst;
156         }
157
158         gen_args[0] = dst;
159         gen_args[1] = src;
160 }
161
162 static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
163 {
164         reset_temp(dst);
165         temps[dst].state = TCG_TEMP_CONST;
166         temps[dst].val = val;
167         gen_args[0] = dst;
168         gen_args[1] = val;
169 }
170
171 static TCGOpcode op_to_mov(TCGOpcode op)
172 {
173     switch (op_bits(op)) {
174     case 32:
175         return INDEX_op_mov_i32;
176     case 64:
177         return INDEX_op_mov_i64;
178     default:
179         fprintf(stderr, "op_to_mov: unexpected return value of "
180                 "function op_bits.\n");
181         tcg_abort();
182     }
183 }
184
185 static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
186 {
187     switch (op) {
188     CASE_OP_32_64(add):
189         return x + y;
190
191     CASE_OP_32_64(sub):
192         return x - y;
193
194     CASE_OP_32_64(mul):
195         return x * y;
196
197     CASE_OP_32_64(and):
198         return x & y;
199
200     CASE_OP_32_64(or):
201         return x | y;
202
203     CASE_OP_32_64(xor):
204         return x ^ y;
205
206     case INDEX_op_shl_i32:
207         return (uint32_t)x << (uint32_t)y;
208
209     case INDEX_op_shl_i64:
210         return (uint64_t)x << (uint64_t)y;
211
212     case INDEX_op_shr_i32:
213         return (uint32_t)x >> (uint32_t)y;
214
215     case INDEX_op_shr_i64:
216         return (uint64_t)x >> (uint64_t)y;
217
218     case INDEX_op_sar_i32:
219         return (int32_t)x >> (int32_t)y;
220
221     case INDEX_op_sar_i64:
222         return (int64_t)x >> (int64_t)y;
223
224     case INDEX_op_rotr_i32:
225         x = ((uint32_t)x << (32 - y)) | ((uint32_t)x >> y);
226         return x;
227
228     case INDEX_op_rotr_i64:
229         x = ((uint64_t)x << (64 - y)) | ((uint64_t)x >> y);
230         return x;
231
232     case INDEX_op_rotl_i32:
233         x = ((uint32_t)x << y) | ((uint32_t)x >> (32 - y));
234         return x;
235
236     case INDEX_op_rotl_i64:
237         x = ((uint64_t)x << y) | ((uint64_t)x >> (64 - y));
238         return x;
239
240     CASE_OP_32_64(not):
241         return ~x;
242
243     CASE_OP_32_64(neg):
244         return -x;
245
246     CASE_OP_32_64(andc):
247         return x & ~y;
248
249     CASE_OP_32_64(orc):
250         return x | ~y;
251
252     CASE_OP_32_64(eqv):
253         return ~(x ^ y);
254
255     CASE_OP_32_64(nand):
256         return ~(x & y);
257
258     CASE_OP_32_64(nor):
259         return ~(x | y);
260
261     CASE_OP_32_64(ext8s):
262         return (int8_t)x;
263
264     CASE_OP_32_64(ext16s):
265         return (int16_t)x;
266
267     CASE_OP_32_64(ext8u):
268         return (uint8_t)x;
269
270     CASE_OP_32_64(ext16u):
271         return (uint16_t)x;
272
273     case INDEX_op_ext32s_i64:
274         return (int32_t)x;
275
276     case INDEX_op_ext32u_i64:
277         return (uint32_t)x;
278
279     default:
280         fprintf(stderr,
281                 "Unrecognized operation %d in do_constant_folding.\n", op);
282         tcg_abort();
283     }
284 }
285
286 static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
287 {
288     TCGArg res = do_constant_folding_2(op, x, y);
289     if (op_bits(op) == 32) {
290         res &= 0xffffffff;
291     }
292     return res;
293 }
294
295 static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
296 {
297     switch (c) {
298     case TCG_COND_EQ:
299         return x == y;
300     case TCG_COND_NE:
301         return x != y;
302     case TCG_COND_LT:
303         return (int32_t)x < (int32_t)y;
304     case TCG_COND_GE:
305         return (int32_t)x >= (int32_t)y;
306     case TCG_COND_LE:
307         return (int32_t)x <= (int32_t)y;
308     case TCG_COND_GT:
309         return (int32_t)x > (int32_t)y;
310     case TCG_COND_LTU:
311         return x < y;
312     case TCG_COND_GEU:
313         return x >= y;
314     case TCG_COND_LEU:
315         return x <= y;
316     case TCG_COND_GTU:
317         return x > y;
318     default:
319         tcg_abort();
320     }
321 }
322
323 static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
324 {
325     switch (c) {
326     case TCG_COND_EQ:
327         return x == y;
328     case TCG_COND_NE:
329         return x != y;
330     case TCG_COND_LT:
331         return (int64_t)x < (int64_t)y;
332     case TCG_COND_GE:
333         return (int64_t)x >= (int64_t)y;
334     case TCG_COND_LE:
335         return (int64_t)x <= (int64_t)y;
336     case TCG_COND_GT:
337         return (int64_t)x > (int64_t)y;
338     case TCG_COND_LTU:
339         return x < y;
340     case TCG_COND_GEU:
341         return x >= y;
342     case TCG_COND_LEU:
343         return x <= y;
344     case TCG_COND_GTU:
345         return x > y;
346     default:
347         tcg_abort();
348     }
349 }
350
351 static bool do_constant_folding_cond_eq(TCGCond c)
352 {
353     switch (c) {
354     case TCG_COND_GT:
355     case TCG_COND_LTU:
356     case TCG_COND_LT:
357     case TCG_COND_GTU:
358     case TCG_COND_NE:
359         return 0;
360     case TCG_COND_GE:
361     case TCG_COND_GEU:
362     case TCG_COND_LE:
363     case TCG_COND_LEU:
364     case TCG_COND_EQ:
365         return 1;
366     default:
367         tcg_abort();
368     }
369 }
370
371 /* Return 2 if the condition can't be simplified, and the result
372    of the condition (0 or 1) if it can */
373 static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
374                                        TCGArg y, TCGCond c)
375 {
376     if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) {
377         switch (op_bits(op)) {
378         case 32:
379             return do_constant_folding_cond_32(temps[x].val, temps[y].val, c);
380         case 64:
381             return do_constant_folding_cond_64(temps[x].val, temps[y].val, c);
382         default:
383             tcg_abort();
384         }
385     } else if (temps_are_copies(x, y)) {
386         return do_constant_folding_cond_eq(c);
387     } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
388         switch (c) {
389         case TCG_COND_LTU:
390             return 0;
391         case TCG_COND_GEU:
392             return 1;
393         default:
394             return 2;
395         }
396     } else {
397         return 2;
398     }
399 }
400
401 static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
402 {
403     TCGArg a1 = *p1, a2 = *p2;
404     int sum = 0;
405     sum += temps[a1].state == TCG_TEMP_CONST;
406     sum -= temps[a2].state == TCG_TEMP_CONST;
407
408     /* Prefer the constant in second argument, and then the form
409        op a, a, b, which is better handled on non-RISC hosts. */
410     if (sum > 0 || (sum == 0 && dest == a2)) {
411         *p1 = a2;
412         *p2 = a1;
413         return true;
414     }
415     return false;
416 }
417
418 static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
419 {
420     int sum = 0;
421     sum += temps[p1[0]].state == TCG_TEMP_CONST;
422     sum += temps[p1[1]].state == TCG_TEMP_CONST;
423     sum -= temps[p2[0]].state == TCG_TEMP_CONST;
424     sum -= temps[p2[1]].state == TCG_TEMP_CONST;
425     if (sum > 0) {
426         TCGArg t;
427         t = p1[0], p1[0] = p2[0], p2[0] = t;
428         t = p1[1], p1[1] = p2[1], p2[1] = t;
429         return true;
430     }
431     return false;
432 }
433
434 /* Propagate constants and copies, fold constant expressions. */
435 static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
436                                     TCGArg *args, TCGOpDef *tcg_op_defs)
437 {
438     int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
439     TCGOpcode op;
440     const TCGOpDef *def;
441     TCGArg *gen_args;
442     TCGArg tmp;
443
444     /* Array VALS has an element for each temp.
445        If this temp holds a constant then its value is kept in VALS' element.
446        If this temp is a copy of other ones then the other copies are
447        available through the doubly linked circular list. */
448
449     nb_temps = s->nb_temps;
450     nb_globals = s->nb_globals;
451     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
452
453     nb_ops = tcg_opc_ptr - gen_opc_buf;
454     gen_args = args;
455     for (op_index = 0; op_index < nb_ops; op_index++) {
456         op = gen_opc_buf[op_index];
457         def = &tcg_op_defs[op];
458         /* Do copy propagation */
459         if (op == INDEX_op_call) {
460             int nb_oargs = args[0] >> 16;
461             int nb_iargs = args[0] & 0xffff;
462             for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
463                 if (temps[args[i]].state == TCG_TEMP_COPY) {
464                     args[i] = find_better_copy(s, args[i]);
465                 }
466             }
467         } else {
468             for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
469                 if (temps[args[i]].state == TCG_TEMP_COPY) {
470                     args[i] = find_better_copy(s, args[i]);
471                 }
472             }
473         }
474
475         /* For commutative operations make constant second argument */
476         switch (op) {
477         CASE_OP_32_64(add):
478         CASE_OP_32_64(mul):
479         CASE_OP_32_64(and):
480         CASE_OP_32_64(or):
481         CASE_OP_32_64(xor):
482         CASE_OP_32_64(eqv):
483         CASE_OP_32_64(nand):
484         CASE_OP_32_64(nor):
485             swap_commutative(args[0], &args[1], &args[2]);
486             break;
487         CASE_OP_32_64(brcond):
488             if (swap_commutative(-1, &args[0], &args[1])) {
489                 args[2] = tcg_swap_cond(args[2]);
490             }
491             break;
492         CASE_OP_32_64(setcond):
493             if (swap_commutative(args[0], &args[1], &args[2])) {
494                 args[3] = tcg_swap_cond(args[3]);
495             }
496             break;
497         CASE_OP_32_64(movcond):
498             if (swap_commutative(-1, &args[1], &args[2])) {
499                 args[5] = tcg_swap_cond(args[5]);
500             }
501             /* For movcond, we canonicalize the "false" input reg to match
502                the destination reg so that the tcg backend can implement
503                a "move if true" operation.  */
504             if (swap_commutative(args[0], &args[4], &args[3])) {
505                 args[5] = tcg_invert_cond(args[5]);
506             }
507             break;
508         case INDEX_op_add2_i32:
509             swap_commutative(args[0], &args[2], &args[4]);
510             swap_commutative(args[1], &args[3], &args[5]);
511             break;
512         case INDEX_op_brcond2_i32:
513             if (swap_commutative2(&args[0], &args[2])) {
514                 args[4] = tcg_swap_cond(args[4]);
515             }
516             break;
517         case INDEX_op_setcond2_i32:
518             if (swap_commutative2(&args[1], &args[3])) {
519                 args[5] = tcg_swap_cond(args[5]);
520             }
521             break;
522         default:
523             break;
524         }
525
526         /* Simplify expressions for "shift/rot r, 0, a => movi r, 0" */
527         switch (op) {
528         CASE_OP_32_64(shl):
529         CASE_OP_32_64(shr):
530         CASE_OP_32_64(sar):
531         CASE_OP_32_64(rotl):
532         CASE_OP_32_64(rotr):
533             if (temps[args[1]].state == TCG_TEMP_CONST
534                 && temps[args[1]].val == 0) {
535                 gen_opc_buf[op_index] = op_to_movi(op);
536                 tcg_opt_gen_movi(gen_args, args[0], 0);
537                 args += 3;
538                 gen_args += 2;
539                 continue;
540             }
541             break;
542         default:
543             break;
544         }
545
546         /* Simplify expression for "op r, a, 0 => mov r, a" cases */
547         switch (op) {
548         CASE_OP_32_64(add):
549         CASE_OP_32_64(sub):
550         CASE_OP_32_64(shl):
551         CASE_OP_32_64(shr):
552         CASE_OP_32_64(sar):
553         CASE_OP_32_64(rotl):
554         CASE_OP_32_64(rotr):
555         CASE_OP_32_64(or):
556         CASE_OP_32_64(xor):
557             if (temps[args[1]].state == TCG_TEMP_CONST) {
558                 /* Proceed with possible constant folding. */
559                 break;
560             }
561             if (temps[args[2]].state == TCG_TEMP_CONST
562                 && temps[args[2]].val == 0) {
563                 if (temps_are_copies(args[0], args[1])) {
564                     gen_opc_buf[op_index] = INDEX_op_nop;
565                 } else {
566                     gen_opc_buf[op_index] = op_to_mov(op);
567                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
568                     gen_args += 2;
569                 }
570                 args += 3;
571                 continue;
572             }
573             break;
574         default:
575             break;
576         }
577
578         /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
579         switch (op) {
580         CASE_OP_32_64(and):
581         CASE_OP_32_64(mul):
582             if ((temps[args[2]].state == TCG_TEMP_CONST
583                 && temps[args[2]].val == 0)) {
584                 gen_opc_buf[op_index] = op_to_movi(op);
585                 tcg_opt_gen_movi(gen_args, args[0], 0);
586                 args += 3;
587                 gen_args += 2;
588                 continue;
589             }
590             break;
591         default:
592             break;
593         }
594
595         /* Simplify expression for "op r, a, a => mov r, a" cases */
596         switch (op) {
597         CASE_OP_32_64(or):
598         CASE_OP_32_64(and):
599             if (temps_are_copies(args[1], args[2])) {
600                 if (temps_are_copies(args[0], args[1])) {
601                     gen_opc_buf[op_index] = INDEX_op_nop;
602                 } else {
603                     gen_opc_buf[op_index] = op_to_mov(op);
604                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
605                     gen_args += 2;
606                 }
607                 args += 3;
608                 continue;
609             }
610             break;
611         default:
612             break;
613         }
614
615         /* Simplify expression for "op r, a, a => movi r, 0" cases */
616         switch (op) {
617         CASE_OP_32_64(sub):
618         CASE_OP_32_64(xor):
619             if (temps_are_copies(args[1], args[2])) {
620                 gen_opc_buf[op_index] = op_to_movi(op);
621                 tcg_opt_gen_movi(gen_args, args[0], 0);
622                 gen_args += 2;
623                 args += 3;
624                 continue;
625             }
626             break;
627         default:
628             break;
629         }
630
631         /* Propagate constants through copy operations and do constant
632            folding.  Constants will be substituted to arguments by register
633            allocator where needed and possible.  Also detect copies. */
634         switch (op) {
635         CASE_OP_32_64(mov):
636             if (temps_are_copies(args[0], args[1])) {
637                 args += 2;
638                 gen_opc_buf[op_index] = INDEX_op_nop;
639                 break;
640             }
641             if (temps[args[1]].state != TCG_TEMP_CONST) {
642                 tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
643                 gen_args += 2;
644                 args += 2;
645                 break;
646             }
647             /* Source argument is constant.  Rewrite the operation and
648                let movi case handle it. */
649             op = op_to_movi(op);
650             gen_opc_buf[op_index] = op;
651             args[1] = temps[args[1]].val;
652             /* fallthrough */
653         CASE_OP_32_64(movi):
654             tcg_opt_gen_movi(gen_args, args[0], args[1]);
655             gen_args += 2;
656             args += 2;
657             break;
658
659         CASE_OP_32_64(not):
660         CASE_OP_32_64(neg):
661         CASE_OP_32_64(ext8s):
662         CASE_OP_32_64(ext8u):
663         CASE_OP_32_64(ext16s):
664         CASE_OP_32_64(ext16u):
665         case INDEX_op_ext32s_i64:
666         case INDEX_op_ext32u_i64:
667             if (temps[args[1]].state == TCG_TEMP_CONST) {
668                 gen_opc_buf[op_index] = op_to_movi(op);
669                 tmp = do_constant_folding(op, temps[args[1]].val, 0);
670                 tcg_opt_gen_movi(gen_args, args[0], tmp);
671                 gen_args += 2;
672                 args += 2;
673                 break;
674             }
675             goto do_default;
676
677         CASE_OP_32_64(add):
678         CASE_OP_32_64(sub):
679         CASE_OP_32_64(mul):
680         CASE_OP_32_64(or):
681         CASE_OP_32_64(and):
682         CASE_OP_32_64(xor):
683         CASE_OP_32_64(shl):
684         CASE_OP_32_64(shr):
685         CASE_OP_32_64(sar):
686         CASE_OP_32_64(rotl):
687         CASE_OP_32_64(rotr):
688         CASE_OP_32_64(andc):
689         CASE_OP_32_64(orc):
690         CASE_OP_32_64(eqv):
691         CASE_OP_32_64(nand):
692         CASE_OP_32_64(nor):
693             if (temps[args[1]].state == TCG_TEMP_CONST
694                 && temps[args[2]].state == TCG_TEMP_CONST) {
695                 gen_opc_buf[op_index] = op_to_movi(op);
696                 tmp = do_constant_folding(op, temps[args[1]].val,
697                                           temps[args[2]].val);
698                 tcg_opt_gen_movi(gen_args, args[0], tmp);
699                 gen_args += 2;
700                 args += 3;
701                 break;
702             }
703             goto do_default;
704
705         CASE_OP_32_64(deposit):
706             if (temps[args[1]].state == TCG_TEMP_CONST
707                 && temps[args[2]].state == TCG_TEMP_CONST) {
708                 gen_opc_buf[op_index] = op_to_movi(op);
709                 tmp = ((1ull << args[4]) - 1);
710                 tmp = (temps[args[1]].val & ~(tmp << args[3]))
711                       | ((temps[args[2]].val & tmp) << args[3]);
712                 tcg_opt_gen_movi(gen_args, args[0], tmp);
713                 gen_args += 2;
714                 args += 5;
715                 break;
716             }
717             goto do_default;
718
719         CASE_OP_32_64(setcond):
720             tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
721             if (tmp != 2) {
722                 gen_opc_buf[op_index] = op_to_movi(op);
723                 tcg_opt_gen_movi(gen_args, args[0], tmp);
724                 gen_args += 2;
725                 args += 4;
726                 break;
727             }
728             goto do_default;
729
730         CASE_OP_32_64(brcond):
731             tmp = do_constant_folding_cond(op, args[0], args[1], args[2]);
732             if (tmp != 2) {
733                 if (tmp) {
734                     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
735                     gen_opc_buf[op_index] = INDEX_op_br;
736                     gen_args[0] = args[3];
737                     gen_args += 1;
738                 } else {
739                     gen_opc_buf[op_index] = INDEX_op_nop;
740                 }
741                 args += 4;
742                 break;
743             }
744             goto do_default;
745
746         CASE_OP_32_64(movcond):
747             tmp = do_constant_folding_cond(op, args[1], args[2], args[5]);
748             if (tmp != 2) {
749                 if (temps_are_copies(args[0], args[4-tmp])) {
750                     gen_opc_buf[op_index] = INDEX_op_nop;
751                 } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
752                     gen_opc_buf[op_index] = op_to_movi(op);
753                     tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
754                     gen_args += 2;
755                 } else {
756                     gen_opc_buf[op_index] = op_to_mov(op);
757                     tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
758                     gen_args += 2;
759                 }
760                 args += 6;
761                 break;
762             }
763             goto do_default;
764
765         case INDEX_op_brcond2_i32:
766             /* Simplify LT/GE comparisons vs zero to a single compare
767                vs the high word of the input.  */
768             if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
769                 && temps[args[2]].state == TCG_TEMP_CONST
770                 && temps[args[3]].state == TCG_TEMP_CONST
771                 && temps[args[2]].val == 0
772                 && temps[args[3]].val == 0) {
773                 gen_opc_buf[op_index] = INDEX_op_brcond_i32;
774                 gen_args[0] = args[1];
775                 gen_args[1] = args[3];
776                 gen_args[2] = args[4];
777                 gen_args[3] = args[5];
778                 gen_args += 4;
779                 args += 6;
780                 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
781                 break;
782             }
783             goto do_default;
784
785         case INDEX_op_setcond2_i32:
786             /* Simplify LT/GE comparisons vs zero to a single compare
787                vs the high word of the input.  */
788             if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
789                 && temps[args[3]].state == TCG_TEMP_CONST
790                 && temps[args[4]].state == TCG_TEMP_CONST
791                 && temps[args[3]].val == 0
792                 && temps[args[4]].val == 0) {
793                 gen_opc_buf[op_index] = INDEX_op_setcond_i32;
794                 gen_args[0] = args[0];
795                 gen_args[1] = args[2];
796                 gen_args[2] = args[4];
797                 gen_args[3] = args[5];
798                 gen_args += 4;
799                 args += 6;
800                 break;
801             }
802             goto do_default;
803
804         case INDEX_op_call:
805             nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
806             if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
807                 for (i = 0; i < nb_globals; i++) {
808                     reset_temp(i);
809                 }
810             }
811             for (i = 0; i < (args[0] >> 16); i++) {
812                 reset_temp(args[i + 1]);
813             }
814             i = nb_call_args + 3;
815             while (i) {
816                 *gen_args = *args;
817                 args++;
818                 gen_args++;
819                 i--;
820             }
821             break;
822
823         default:
824         do_default:
825             /* Default case: we know nothing about operation (or were unable
826                to compute the operation result) so no propagation is done.
827                We trash everything if the operation is the end of a basic
828                block, otherwise we only trash the output args.  */
829             if (def->flags & TCG_OPF_BB_END) {
830                 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
831             } else {
832                 for (i = 0; i < def->nb_oargs; i++) {
833                     reset_temp(args[i]);
834                 }
835             }
836             for (i = 0; i < def->nb_args; i++) {
837                 gen_args[i] = args[i];
838             }
839             args += def->nb_args;
840             gen_args += def->nb_args;
841             break;
842         }
843     }
844
845     return gen_args;
846 }
847
848 TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
849         TCGArg *args, TCGOpDef *tcg_op_defs)
850 {
851     TCGArg *res;
852     res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
853     return res;
854 }
This page took 0.068786 seconds and 4 git commands to generate.