xref: /openbmc/qemu/tcg/optimize.c (revision 3c94193e)
18f2e8c07SKirill Batuzov /*
28f2e8c07SKirill Batuzov  * Optimizations for Tiny Code Generator for QEMU
38f2e8c07SKirill Batuzov  *
48f2e8c07SKirill Batuzov  * Copyright (c) 2010 Samsung Electronics.
58f2e8c07SKirill Batuzov  * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
68f2e8c07SKirill Batuzov  *
78f2e8c07SKirill Batuzov  * Permission is hereby granted, free of charge, to any person obtaining a copy
88f2e8c07SKirill Batuzov  * of this software and associated documentation files (the "Software"), to deal
98f2e8c07SKirill Batuzov  * in the Software without restriction, including without limitation the rights
108f2e8c07SKirill Batuzov  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
118f2e8c07SKirill Batuzov  * copies of the Software, and to permit persons to whom the Software is
128f2e8c07SKirill Batuzov  * furnished to do so, subject to the following conditions:
138f2e8c07SKirill Batuzov  *
148f2e8c07SKirill Batuzov  * The above copyright notice and this permission notice shall be included in
158f2e8c07SKirill Batuzov  * all copies or substantial portions of the Software.
168f2e8c07SKirill Batuzov  *
178f2e8c07SKirill Batuzov  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
188f2e8c07SKirill Batuzov  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
198f2e8c07SKirill Batuzov  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
208f2e8c07SKirill Batuzov  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
218f2e8c07SKirill Batuzov  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
228f2e8c07SKirill Batuzov  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
238f2e8c07SKirill Batuzov  * THE SOFTWARE.
248f2e8c07SKirill Batuzov  */
258f2e8c07SKirill Batuzov 
268f2e8c07SKirill Batuzov #include "config.h"
278f2e8c07SKirill Batuzov 
288f2e8c07SKirill Batuzov #include <stdlib.h>
298f2e8c07SKirill Batuzov #include <stdio.h>
308f2e8c07SKirill Batuzov 
318f2e8c07SKirill Batuzov #include "qemu-common.h"
328f2e8c07SKirill Batuzov #include "tcg-op.h"
338f2e8c07SKirill Batuzov 
348f2e8c07SKirill Batuzov #define CASE_OP_32_64(x)                        \
358f2e8c07SKirill Batuzov         glue(glue(case INDEX_op_, x), _i32):    \
368f2e8c07SKirill Batuzov         glue(glue(case INDEX_op_, x), _i64)
378f2e8c07SKirill Batuzov 
3822613af4SKirill Batuzov typedef enum {
3922613af4SKirill Batuzov     TCG_TEMP_UNDEF = 0,
4022613af4SKirill Batuzov     TCG_TEMP_CONST,
4122613af4SKirill Batuzov     TCG_TEMP_COPY,
4222613af4SKirill Batuzov } tcg_temp_state;
4322613af4SKirill Batuzov 
4422613af4SKirill Batuzov struct tcg_temp_info {
4522613af4SKirill Batuzov     tcg_temp_state state;
4622613af4SKirill Batuzov     uint16_t prev_copy;
4722613af4SKirill Batuzov     uint16_t next_copy;
4822613af4SKirill Batuzov     tcg_target_ulong val;
4922613af4SKirill Batuzov };
5022613af4SKirill Batuzov 
5122613af4SKirill Batuzov static struct tcg_temp_info temps[TCG_MAX_TEMPS];
5222613af4SKirill Batuzov 
53e590d4e6SAurelien Jarno /* Reset TEMP's state to TCG_TEMP_UNDEF.  If TEMP only had one copy, remove
54e590d4e6SAurelien Jarno    the copy flag from the left temp.  */
55e590d4e6SAurelien Jarno static void reset_temp(TCGArg temp)
5622613af4SKirill Batuzov {
57e590d4e6SAurelien Jarno     if (temps[temp].state == TCG_TEMP_COPY) {
58e590d4e6SAurelien Jarno         if (temps[temp].prev_copy == temps[temp].next_copy) {
59e590d4e6SAurelien Jarno             temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF;
6022613af4SKirill Batuzov         } else {
6122613af4SKirill Batuzov             temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
6222613af4SKirill Batuzov             temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
63e590d4e6SAurelien Jarno         }
6422613af4SKirill Batuzov     }
6548b56ce1SAurelien Jarno     temps[temp].state = TCG_TEMP_UNDEF;
6622613af4SKirill Batuzov }
6722613af4SKirill Batuzov 
68fe0de7aaSBlue Swirl static int op_bits(TCGOpcode op)
6922613af4SKirill Batuzov {
708399ad59SRichard Henderson     const TCGOpDef *def = &tcg_op_defs[op];
718399ad59SRichard Henderson     return def->flags & TCG_OPF_64BIT ? 64 : 32;
7222613af4SKirill Batuzov }
7322613af4SKirill Batuzov 
74fe0de7aaSBlue Swirl static TCGOpcode op_to_movi(TCGOpcode op)
7522613af4SKirill Batuzov {
7622613af4SKirill Batuzov     switch (op_bits(op)) {
7722613af4SKirill Batuzov     case 32:
7822613af4SKirill Batuzov         return INDEX_op_movi_i32;
7922613af4SKirill Batuzov     case 64:
8022613af4SKirill Batuzov         return INDEX_op_movi_i64;
8122613af4SKirill Batuzov     default:
8222613af4SKirill Batuzov         fprintf(stderr, "op_to_movi: unexpected return value of "
8322613af4SKirill Batuzov                 "function op_bits.\n");
8422613af4SKirill Batuzov         tcg_abort();
8522613af4SKirill Batuzov     }
8622613af4SKirill Batuzov }
8722613af4SKirill Batuzov 
88e590d4e6SAurelien Jarno static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
89e590d4e6SAurelien Jarno {
90e590d4e6SAurelien Jarno     TCGArg i;
91e590d4e6SAurelien Jarno 
92e590d4e6SAurelien Jarno     /* If this is already a global, we can't do better. */
93e590d4e6SAurelien Jarno     if (temp < s->nb_globals) {
94e590d4e6SAurelien Jarno         return temp;
95e590d4e6SAurelien Jarno     }
96e590d4e6SAurelien Jarno 
97e590d4e6SAurelien Jarno     /* Search for a global first. */
98e590d4e6SAurelien Jarno     for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
99e590d4e6SAurelien Jarno         if (i < s->nb_globals) {
100e590d4e6SAurelien Jarno             return i;
101e590d4e6SAurelien Jarno         }
102e590d4e6SAurelien Jarno     }
103e590d4e6SAurelien Jarno 
104e590d4e6SAurelien Jarno     /* If it is a temp, search for a temp local. */
105e590d4e6SAurelien Jarno     if (!s->temps[temp].temp_local) {
106e590d4e6SAurelien Jarno         for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
107e590d4e6SAurelien Jarno             if (s->temps[i].temp_local) {
108e590d4e6SAurelien Jarno                 return i;
109e590d4e6SAurelien Jarno             }
110e590d4e6SAurelien Jarno         }
111e590d4e6SAurelien Jarno     }
112e590d4e6SAurelien Jarno 
113e590d4e6SAurelien Jarno     /* Failure to find a better representation, return the same temp. */
114e590d4e6SAurelien Jarno     return temp;
115e590d4e6SAurelien Jarno }
116e590d4e6SAurelien Jarno 
117e590d4e6SAurelien Jarno static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
118e590d4e6SAurelien Jarno {
119e590d4e6SAurelien Jarno     TCGArg i;
120e590d4e6SAurelien Jarno 
121e590d4e6SAurelien Jarno     if (arg1 == arg2) {
122e590d4e6SAurelien Jarno         return true;
123e590d4e6SAurelien Jarno     }
124e590d4e6SAurelien Jarno 
125e590d4e6SAurelien Jarno     if (temps[arg1].state != TCG_TEMP_COPY
126e590d4e6SAurelien Jarno         || temps[arg2].state != TCG_TEMP_COPY) {
127e590d4e6SAurelien Jarno         return false;
128e590d4e6SAurelien Jarno     }
129e590d4e6SAurelien Jarno 
130e590d4e6SAurelien Jarno     for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
131e590d4e6SAurelien Jarno         if (i == arg2) {
132e590d4e6SAurelien Jarno             return true;
133e590d4e6SAurelien Jarno         }
134e590d4e6SAurelien Jarno     }
135e590d4e6SAurelien Jarno 
136e590d4e6SAurelien Jarno     return false;
137e590d4e6SAurelien Jarno }
138e590d4e6SAurelien Jarno 
139b80bb016SAurelien Jarno static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
140b80bb016SAurelien Jarno                             TCGArg dst, TCGArg src)
14122613af4SKirill Batuzov {
142e590d4e6SAurelien Jarno         reset_temp(dst);
14322613af4SKirill Batuzov         assert(temps[src].state != TCG_TEMP_CONST);
144e590d4e6SAurelien Jarno 
145e590d4e6SAurelien Jarno         if (s->temps[src].type == s->temps[dst].type) {
146e590d4e6SAurelien Jarno             if (temps[src].state != TCG_TEMP_COPY) {
147e590d4e6SAurelien Jarno                 temps[src].state = TCG_TEMP_COPY;
14822613af4SKirill Batuzov                 temps[src].next_copy = src;
14922613af4SKirill Batuzov                 temps[src].prev_copy = src;
15022613af4SKirill Batuzov             }
15122613af4SKirill Batuzov             temps[dst].state = TCG_TEMP_COPY;
15222613af4SKirill Batuzov             temps[dst].next_copy = temps[src].next_copy;
15322613af4SKirill Batuzov             temps[dst].prev_copy = src;
15422613af4SKirill Batuzov             temps[temps[dst].next_copy].prev_copy = dst;
15522613af4SKirill Batuzov             temps[src].next_copy = dst;
15622613af4SKirill Batuzov         }
157e590d4e6SAurelien Jarno 
15822613af4SKirill Batuzov         gen_args[0] = dst;
15922613af4SKirill Batuzov         gen_args[1] = src;
16022613af4SKirill Batuzov }
16122613af4SKirill Batuzov 
162e590d4e6SAurelien Jarno static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
16322613af4SKirill Batuzov {
164e590d4e6SAurelien Jarno         reset_temp(dst);
16522613af4SKirill Batuzov         temps[dst].state = TCG_TEMP_CONST;
16622613af4SKirill Batuzov         temps[dst].val = val;
16722613af4SKirill Batuzov         gen_args[0] = dst;
16822613af4SKirill Batuzov         gen_args[1] = val;
16922613af4SKirill Batuzov }
17022613af4SKirill Batuzov 
171fe0de7aaSBlue Swirl static TCGOpcode op_to_mov(TCGOpcode op)
17253108fb5SKirill Batuzov {
17353108fb5SKirill Batuzov     switch (op_bits(op)) {
17453108fb5SKirill Batuzov     case 32:
17553108fb5SKirill Batuzov         return INDEX_op_mov_i32;
17653108fb5SKirill Batuzov     case 64:
17753108fb5SKirill Batuzov         return INDEX_op_mov_i64;
17853108fb5SKirill Batuzov     default:
17953108fb5SKirill Batuzov         fprintf(stderr, "op_to_mov: unexpected return value of "
18053108fb5SKirill Batuzov                 "function op_bits.\n");
18153108fb5SKirill Batuzov         tcg_abort();
18253108fb5SKirill Batuzov     }
18353108fb5SKirill Batuzov }
18453108fb5SKirill Batuzov 
185fe0de7aaSBlue Swirl static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
18653108fb5SKirill Batuzov {
18753108fb5SKirill Batuzov     switch (op) {
18853108fb5SKirill Batuzov     CASE_OP_32_64(add):
18953108fb5SKirill Batuzov         return x + y;
19053108fb5SKirill Batuzov 
19153108fb5SKirill Batuzov     CASE_OP_32_64(sub):
19253108fb5SKirill Batuzov         return x - y;
19353108fb5SKirill Batuzov 
19453108fb5SKirill Batuzov     CASE_OP_32_64(mul):
19553108fb5SKirill Batuzov         return x * y;
19653108fb5SKirill Batuzov 
1979a81090bSKirill Batuzov     CASE_OP_32_64(and):
1989a81090bSKirill Batuzov         return x & y;
1999a81090bSKirill Batuzov 
2009a81090bSKirill Batuzov     CASE_OP_32_64(or):
2019a81090bSKirill Batuzov         return x | y;
2029a81090bSKirill Batuzov 
2039a81090bSKirill Batuzov     CASE_OP_32_64(xor):
2049a81090bSKirill Batuzov         return x ^ y;
2059a81090bSKirill Batuzov 
20655c0975cSKirill Batuzov     case INDEX_op_shl_i32:
20755c0975cSKirill Batuzov         return (uint32_t)x << (uint32_t)y;
20855c0975cSKirill Batuzov 
20955c0975cSKirill Batuzov     case INDEX_op_shl_i64:
21055c0975cSKirill Batuzov         return (uint64_t)x << (uint64_t)y;
21155c0975cSKirill Batuzov 
21255c0975cSKirill Batuzov     case INDEX_op_shr_i32:
21355c0975cSKirill Batuzov         return (uint32_t)x >> (uint32_t)y;
21455c0975cSKirill Batuzov 
21555c0975cSKirill Batuzov     case INDEX_op_shr_i64:
21655c0975cSKirill Batuzov         return (uint64_t)x >> (uint64_t)y;
21755c0975cSKirill Batuzov 
21855c0975cSKirill Batuzov     case INDEX_op_sar_i32:
21955c0975cSKirill Batuzov         return (int32_t)x >> (int32_t)y;
22055c0975cSKirill Batuzov 
22155c0975cSKirill Batuzov     case INDEX_op_sar_i64:
22255c0975cSKirill Batuzov         return (int64_t)x >> (int64_t)y;
22355c0975cSKirill Batuzov 
22455c0975cSKirill Batuzov     case INDEX_op_rotr_i32:
22525c4d9ccSRichard Henderson         x = ((uint32_t)x << (32 - y)) | ((uint32_t)x >> y);
22655c0975cSKirill Batuzov         return x;
22755c0975cSKirill Batuzov 
22855c0975cSKirill Batuzov     case INDEX_op_rotr_i64:
22925c4d9ccSRichard Henderson         x = ((uint64_t)x << (64 - y)) | ((uint64_t)x >> y);
23055c0975cSKirill Batuzov         return x;
23155c0975cSKirill Batuzov 
23255c0975cSKirill Batuzov     case INDEX_op_rotl_i32:
23325c4d9ccSRichard Henderson         x = ((uint32_t)x << y) | ((uint32_t)x >> (32 - y));
23455c0975cSKirill Batuzov         return x;
23555c0975cSKirill Batuzov 
23655c0975cSKirill Batuzov     case INDEX_op_rotl_i64:
23725c4d9ccSRichard Henderson         x = ((uint64_t)x << y) | ((uint64_t)x >> (64 - y));
23855c0975cSKirill Batuzov         return x;
23955c0975cSKirill Batuzov 
24025c4d9ccSRichard Henderson     CASE_OP_32_64(not):
241a640f031SKirill Batuzov         return ~x;
242a640f031SKirill Batuzov 
243cb25c80aSRichard Henderson     CASE_OP_32_64(neg):
244cb25c80aSRichard Henderson         return -x;
245cb25c80aSRichard Henderson 
246cb25c80aSRichard Henderson     CASE_OP_32_64(andc):
247cb25c80aSRichard Henderson         return x & ~y;
248cb25c80aSRichard Henderson 
249cb25c80aSRichard Henderson     CASE_OP_32_64(orc):
250cb25c80aSRichard Henderson         return x | ~y;
251cb25c80aSRichard Henderson 
252cb25c80aSRichard Henderson     CASE_OP_32_64(eqv):
253cb25c80aSRichard Henderson         return ~(x ^ y);
254cb25c80aSRichard Henderson 
255cb25c80aSRichard Henderson     CASE_OP_32_64(nand):
256cb25c80aSRichard Henderson         return ~(x & y);
257cb25c80aSRichard Henderson 
258cb25c80aSRichard Henderson     CASE_OP_32_64(nor):
259cb25c80aSRichard Henderson         return ~(x | y);
260cb25c80aSRichard Henderson 
26125c4d9ccSRichard Henderson     CASE_OP_32_64(ext8s):
262a640f031SKirill Batuzov         return (int8_t)x;
263a640f031SKirill Batuzov 
26425c4d9ccSRichard Henderson     CASE_OP_32_64(ext16s):
265a640f031SKirill Batuzov         return (int16_t)x;
266a640f031SKirill Batuzov 
26725c4d9ccSRichard Henderson     CASE_OP_32_64(ext8u):
268a640f031SKirill Batuzov         return (uint8_t)x;
269a640f031SKirill Batuzov 
27025c4d9ccSRichard Henderson     CASE_OP_32_64(ext16u):
271a640f031SKirill Batuzov         return (uint16_t)x;
272a640f031SKirill Batuzov 
273a640f031SKirill Batuzov     case INDEX_op_ext32s_i64:
274a640f031SKirill Batuzov         return (int32_t)x;
275a640f031SKirill Batuzov 
276a640f031SKirill Batuzov     case INDEX_op_ext32u_i64:
277a640f031SKirill Batuzov         return (uint32_t)x;
278a640f031SKirill Batuzov 
27953108fb5SKirill Batuzov     default:
28053108fb5SKirill Batuzov         fprintf(stderr,
28153108fb5SKirill Batuzov                 "Unrecognized operation %d in do_constant_folding.\n", op);
28253108fb5SKirill Batuzov         tcg_abort();
28353108fb5SKirill Batuzov     }
28453108fb5SKirill Batuzov }
28553108fb5SKirill Batuzov 
286fe0de7aaSBlue Swirl static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
28753108fb5SKirill Batuzov {
28853108fb5SKirill Batuzov     TCGArg res = do_constant_folding_2(op, x, y);
28953108fb5SKirill Batuzov     if (op_bits(op) == 32) {
29053108fb5SKirill Batuzov         res &= 0xffffffff;
29153108fb5SKirill Batuzov     }
29253108fb5SKirill Batuzov     return res;
29353108fb5SKirill Batuzov }
29453108fb5SKirill Batuzov 
295f8dd19e5SAurelien Jarno static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
296f8dd19e5SAurelien Jarno                                        TCGArg y, TCGCond c)
297f8dd19e5SAurelien Jarno {
298f8dd19e5SAurelien Jarno     switch (op_bits(op)) {
299f8dd19e5SAurelien Jarno     case 32:
300f8dd19e5SAurelien Jarno         switch (c) {
301f8dd19e5SAurelien Jarno         case TCG_COND_EQ:
302f8dd19e5SAurelien Jarno             return (uint32_t)x == (uint32_t)y;
303f8dd19e5SAurelien Jarno         case TCG_COND_NE:
304f8dd19e5SAurelien Jarno             return (uint32_t)x != (uint32_t)y;
305f8dd19e5SAurelien Jarno         case TCG_COND_LT:
306f8dd19e5SAurelien Jarno             return (int32_t)x < (int32_t)y;
307f8dd19e5SAurelien Jarno         case TCG_COND_GE:
308f8dd19e5SAurelien Jarno             return (int32_t)x >= (int32_t)y;
309f8dd19e5SAurelien Jarno         case TCG_COND_LE:
310f8dd19e5SAurelien Jarno             return (int32_t)x <= (int32_t)y;
311f8dd19e5SAurelien Jarno         case TCG_COND_GT:
312f8dd19e5SAurelien Jarno             return (int32_t)x > (int32_t)y;
313f8dd19e5SAurelien Jarno         case TCG_COND_LTU:
314f8dd19e5SAurelien Jarno             return (uint32_t)x < (uint32_t)y;
315f8dd19e5SAurelien Jarno         case TCG_COND_GEU:
316f8dd19e5SAurelien Jarno             return (uint32_t)x >= (uint32_t)y;
317f8dd19e5SAurelien Jarno         case TCG_COND_LEU:
318f8dd19e5SAurelien Jarno             return (uint32_t)x <= (uint32_t)y;
319f8dd19e5SAurelien Jarno         case TCG_COND_GTU:
320f8dd19e5SAurelien Jarno             return (uint32_t)x > (uint32_t)y;
321f8dd19e5SAurelien Jarno         }
322f8dd19e5SAurelien Jarno         break;
323f8dd19e5SAurelien Jarno     case 64:
324f8dd19e5SAurelien Jarno         switch (c) {
325f8dd19e5SAurelien Jarno         case TCG_COND_EQ:
326f8dd19e5SAurelien Jarno             return (uint64_t)x == (uint64_t)y;
327f8dd19e5SAurelien Jarno         case TCG_COND_NE:
328f8dd19e5SAurelien Jarno             return (uint64_t)x != (uint64_t)y;
329f8dd19e5SAurelien Jarno         case TCG_COND_LT:
330f8dd19e5SAurelien Jarno             return (int64_t)x < (int64_t)y;
331f8dd19e5SAurelien Jarno         case TCG_COND_GE:
332f8dd19e5SAurelien Jarno             return (int64_t)x >= (int64_t)y;
333f8dd19e5SAurelien Jarno         case TCG_COND_LE:
334f8dd19e5SAurelien Jarno             return (int64_t)x <= (int64_t)y;
335f8dd19e5SAurelien Jarno         case TCG_COND_GT:
336f8dd19e5SAurelien Jarno             return (int64_t)x > (int64_t)y;
337f8dd19e5SAurelien Jarno         case TCG_COND_LTU:
338f8dd19e5SAurelien Jarno             return (uint64_t)x < (uint64_t)y;
339f8dd19e5SAurelien Jarno         case TCG_COND_GEU:
340f8dd19e5SAurelien Jarno             return (uint64_t)x >= (uint64_t)y;
341f8dd19e5SAurelien Jarno         case TCG_COND_LEU:
342f8dd19e5SAurelien Jarno             return (uint64_t)x <= (uint64_t)y;
343f8dd19e5SAurelien Jarno         case TCG_COND_GTU:
344f8dd19e5SAurelien Jarno             return (uint64_t)x > (uint64_t)y;
345f8dd19e5SAurelien Jarno         }
346f8dd19e5SAurelien Jarno         break;
347f8dd19e5SAurelien Jarno     }
348f8dd19e5SAurelien Jarno 
349f8dd19e5SAurelien Jarno     fprintf(stderr,
350f8dd19e5SAurelien Jarno             "Unrecognized bitness %d or condition %d in "
351f8dd19e5SAurelien Jarno             "do_constant_folding_cond.\n", op_bits(op), c);
352f8dd19e5SAurelien Jarno     tcg_abort();
353f8dd19e5SAurelien Jarno }
354f8dd19e5SAurelien Jarno 
35522613af4SKirill Batuzov /* Propagate constants and copies, fold constant expressions. */
3568f2e8c07SKirill Batuzov static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
3578f2e8c07SKirill Batuzov                                     TCGArg *args, TCGOpDef *tcg_op_defs)
3588f2e8c07SKirill Batuzov {
359fe0de7aaSBlue Swirl     int i, nb_ops, op_index, nb_temps, nb_globals, nb_call_args;
360fe0de7aaSBlue Swirl     TCGOpcode op;
3618f2e8c07SKirill Batuzov     const TCGOpDef *def;
3628f2e8c07SKirill Batuzov     TCGArg *gen_args;
36353108fb5SKirill Batuzov     TCGArg tmp;
3645d8f5363SRichard Henderson     TCGCond cond;
3655d8f5363SRichard Henderson 
36622613af4SKirill Batuzov     /* Array VALS has an element for each temp.
36722613af4SKirill Batuzov        If this temp holds a constant then its value is kept in VALS' element.
368e590d4e6SAurelien Jarno        If this temp is a copy of other ones then the other copies are
369e590d4e6SAurelien Jarno        available through the doubly linked circular list. */
3708f2e8c07SKirill Batuzov 
3718f2e8c07SKirill Batuzov     nb_temps = s->nb_temps;
3728f2e8c07SKirill Batuzov     nb_globals = s->nb_globals;
37322613af4SKirill Batuzov     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
3748f2e8c07SKirill Batuzov 
3758f2e8c07SKirill Batuzov     nb_ops = tcg_opc_ptr - gen_opc_buf;
3768f2e8c07SKirill Batuzov     gen_args = args;
3778f2e8c07SKirill Batuzov     for (op_index = 0; op_index < nb_ops; op_index++) {
3788f2e8c07SKirill Batuzov         op = gen_opc_buf[op_index];
3798f2e8c07SKirill Batuzov         def = &tcg_op_defs[op];
38022613af4SKirill Batuzov         /* Do copy propagation */
3811ff8c541SAurelien Jarno         if (op == INDEX_op_call) {
3821ff8c541SAurelien Jarno             int nb_oargs = args[0] >> 16;
3831ff8c541SAurelien Jarno             int nb_iargs = args[0] & 0xffff;
3841ff8c541SAurelien Jarno             for (i = nb_oargs + 1; i < nb_oargs + nb_iargs + 1; i++) {
3851ff8c541SAurelien Jarno                 if (temps[args[i]].state == TCG_TEMP_COPY) {
3861ff8c541SAurelien Jarno                     args[i] = find_better_copy(s, args[i]);
3871ff8c541SAurelien Jarno                 }
3881ff8c541SAurelien Jarno             }
3891ff8c541SAurelien Jarno         } else {
39022613af4SKirill Batuzov             for (i = def->nb_oargs; i < def->nb_oargs + def->nb_iargs; i++) {
39122613af4SKirill Batuzov                 if (temps[args[i]].state == TCG_TEMP_COPY) {
392e590d4e6SAurelien Jarno                     args[i] = find_better_copy(s, args[i]);
39322613af4SKirill Batuzov                 }
39422613af4SKirill Batuzov             }
39522613af4SKirill Batuzov         }
39622613af4SKirill Batuzov 
39753108fb5SKirill Batuzov         /* For commutative operations make constant second argument */
39853108fb5SKirill Batuzov         switch (op) {
39953108fb5SKirill Batuzov         CASE_OP_32_64(add):
40053108fb5SKirill Batuzov         CASE_OP_32_64(mul):
4019a81090bSKirill Batuzov         CASE_OP_32_64(and):
4029a81090bSKirill Batuzov         CASE_OP_32_64(or):
4039a81090bSKirill Batuzov         CASE_OP_32_64(xor):
404cb25c80aSRichard Henderson         CASE_OP_32_64(eqv):
405cb25c80aSRichard Henderson         CASE_OP_32_64(nand):
406cb25c80aSRichard Henderson         CASE_OP_32_64(nor):
40753108fb5SKirill Batuzov             if (temps[args[1]].state == TCG_TEMP_CONST) {
40853108fb5SKirill Batuzov                 tmp = args[1];
40953108fb5SKirill Batuzov                 args[1] = args[2];
41053108fb5SKirill Batuzov                 args[2] = tmp;
41153108fb5SKirill Batuzov             }
41253108fb5SKirill Batuzov             break;
41365a7cce1SAurelien Jarno         CASE_OP_32_64(brcond):
41465a7cce1SAurelien Jarno             if (temps[args[0]].state == TCG_TEMP_CONST
41565a7cce1SAurelien Jarno                 && temps[args[1]].state != TCG_TEMP_CONST) {
41665a7cce1SAurelien Jarno                 tmp = args[0];
41765a7cce1SAurelien Jarno                 args[0] = args[1];
41865a7cce1SAurelien Jarno                 args[1] = tmp;
41965a7cce1SAurelien Jarno                 args[2] = tcg_swap_cond(args[2]);
42065a7cce1SAurelien Jarno             }
42165a7cce1SAurelien Jarno             break;
42265a7cce1SAurelien Jarno         CASE_OP_32_64(setcond):
42365a7cce1SAurelien Jarno             if (temps[args[1]].state == TCG_TEMP_CONST
42465a7cce1SAurelien Jarno                 && temps[args[2]].state != TCG_TEMP_CONST) {
42565a7cce1SAurelien Jarno                 tmp = args[1];
42665a7cce1SAurelien Jarno                 args[1] = args[2];
42765a7cce1SAurelien Jarno                 args[2] = tmp;
42865a7cce1SAurelien Jarno                 args[3] = tcg_swap_cond(args[3]);
42965a7cce1SAurelien Jarno             }
43065a7cce1SAurelien Jarno             break;
431fa01a208SRichard Henderson         CASE_OP_32_64(movcond):
4325d8f5363SRichard Henderson             cond = args[5];
433fa01a208SRichard Henderson             if (temps[args[1]].state == TCG_TEMP_CONST
434fa01a208SRichard Henderson                 && temps[args[2]].state != TCG_TEMP_CONST) {
435fa01a208SRichard Henderson                 tmp = args[1];
436fa01a208SRichard Henderson                 args[1] = args[2];
437fa01a208SRichard Henderson                 args[2] = tmp;
4385d8f5363SRichard Henderson                 cond = tcg_swap_cond(cond);
439fa01a208SRichard Henderson             }
4405d8f5363SRichard Henderson             /* For movcond, we canonicalize the "false" input reg to match
4415d8f5363SRichard Henderson                the destination reg so that the tcg backend can implement
4425d8f5363SRichard Henderson                a "move if true" operation.  */
4435d8f5363SRichard Henderson             if (args[0] == args[3]) {
4445d8f5363SRichard Henderson                 tmp = args[3];
4455d8f5363SRichard Henderson                 args[3] = args[4];
4465d8f5363SRichard Henderson                 args[4] = tmp;
4475d8f5363SRichard Henderson                 cond = tcg_invert_cond(cond);
4485d8f5363SRichard Henderson             }
4495d8f5363SRichard Henderson             args[5] = cond;
45053108fb5SKirill Batuzov         default:
45153108fb5SKirill Batuzov             break;
45253108fb5SKirill Batuzov         }
45353108fb5SKirill Batuzov 
45401ee5282SAurelien Jarno         /* Simplify expressions for "shift/rot r, 0, a => movi r, 0" */
45501ee5282SAurelien Jarno         switch (op) {
45601ee5282SAurelien Jarno         CASE_OP_32_64(shl):
45701ee5282SAurelien Jarno         CASE_OP_32_64(shr):
45801ee5282SAurelien Jarno         CASE_OP_32_64(sar):
45901ee5282SAurelien Jarno         CASE_OP_32_64(rotl):
46001ee5282SAurelien Jarno         CASE_OP_32_64(rotr):
46101ee5282SAurelien Jarno             if (temps[args[1]].state == TCG_TEMP_CONST
46201ee5282SAurelien Jarno                 && temps[args[1]].val == 0) {
46301ee5282SAurelien Jarno                 gen_opc_buf[op_index] = op_to_movi(op);
464e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], 0);
46501ee5282SAurelien Jarno                 args += 3;
46601ee5282SAurelien Jarno                 gen_args += 2;
46701ee5282SAurelien Jarno                 continue;
46801ee5282SAurelien Jarno             }
46901ee5282SAurelien Jarno             break;
47001ee5282SAurelien Jarno         default:
47101ee5282SAurelien Jarno             break;
47201ee5282SAurelien Jarno         }
47301ee5282SAurelien Jarno 
47456e49438SAurelien Jarno         /* Simplify expression for "op r, a, 0 => mov r, a" cases */
47553108fb5SKirill Batuzov         switch (op) {
47653108fb5SKirill Batuzov         CASE_OP_32_64(add):
47753108fb5SKirill Batuzov         CASE_OP_32_64(sub):
47855c0975cSKirill Batuzov         CASE_OP_32_64(shl):
47955c0975cSKirill Batuzov         CASE_OP_32_64(shr):
48055c0975cSKirill Batuzov         CASE_OP_32_64(sar):
48125c4d9ccSRichard Henderson         CASE_OP_32_64(rotl):
48225c4d9ccSRichard Henderson         CASE_OP_32_64(rotr):
48338ee188bSAurelien Jarno         CASE_OP_32_64(or):
48438ee188bSAurelien Jarno         CASE_OP_32_64(xor):
48553108fb5SKirill Batuzov             if (temps[args[1]].state == TCG_TEMP_CONST) {
48653108fb5SKirill Batuzov                 /* Proceed with possible constant folding. */
48753108fb5SKirill Batuzov                 break;
48853108fb5SKirill Batuzov             }
48953108fb5SKirill Batuzov             if (temps[args[2]].state == TCG_TEMP_CONST
49053108fb5SKirill Batuzov                 && temps[args[2]].val == 0) {
491e590d4e6SAurelien Jarno                 if (temps_are_copies(args[0], args[1])) {
49253108fb5SKirill Batuzov                     gen_opc_buf[op_index] = INDEX_op_nop;
49353108fb5SKirill Batuzov                 } else {
49453108fb5SKirill Batuzov                     gen_opc_buf[op_index] = op_to_mov(op);
495b80bb016SAurelien Jarno                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
49653108fb5SKirill Batuzov                     gen_args += 2;
49753108fb5SKirill Batuzov                 }
498fedc0da2SAurelien Jarno                 args += 3;
49953108fb5SKirill Batuzov                 continue;
50053108fb5SKirill Batuzov             }
50153108fb5SKirill Batuzov             break;
50256e49438SAurelien Jarno         default:
50356e49438SAurelien Jarno             break;
50456e49438SAurelien Jarno         }
50556e49438SAurelien Jarno 
50656e49438SAurelien Jarno         /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
50756e49438SAurelien Jarno         switch (op) {
50861251c0cSAurelien Jarno         CASE_OP_32_64(and):
50953108fb5SKirill Batuzov         CASE_OP_32_64(mul):
51053108fb5SKirill Batuzov             if ((temps[args[2]].state == TCG_TEMP_CONST
51153108fb5SKirill Batuzov                 && temps[args[2]].val == 0)) {
51253108fb5SKirill Batuzov                 gen_opc_buf[op_index] = op_to_movi(op);
513e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], 0);
51453108fb5SKirill Batuzov                 args += 3;
51553108fb5SKirill Batuzov                 gen_args += 2;
51653108fb5SKirill Batuzov                 continue;
51753108fb5SKirill Batuzov             }
51853108fb5SKirill Batuzov             break;
51956e49438SAurelien Jarno         default:
52056e49438SAurelien Jarno             break;
52156e49438SAurelien Jarno         }
52256e49438SAurelien Jarno 
52356e49438SAurelien Jarno         /* Simplify expression for "op r, a, a => mov r, a" cases */
52456e49438SAurelien Jarno         switch (op) {
5259a81090bSKirill Batuzov         CASE_OP_32_64(or):
5269a81090bSKirill Batuzov         CASE_OP_32_64(and):
5270aba1c73SAurelien Jarno             if (temps_are_copies(args[1], args[2])) {
528e590d4e6SAurelien Jarno                 if (temps_are_copies(args[0], args[1])) {
5299a81090bSKirill Batuzov                     gen_opc_buf[op_index] = INDEX_op_nop;
5309a81090bSKirill Batuzov                 } else {
5319a81090bSKirill Batuzov                     gen_opc_buf[op_index] = op_to_mov(op);
532b80bb016SAurelien Jarno                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
5339a81090bSKirill Batuzov                     gen_args += 2;
5349a81090bSKirill Batuzov                 }
535fedc0da2SAurelien Jarno                 args += 3;
5369a81090bSKirill Batuzov                 continue;
5379a81090bSKirill Batuzov             }
5389a81090bSKirill Batuzov             break;
539fe0de7aaSBlue Swirl         default:
540fe0de7aaSBlue Swirl             break;
54153108fb5SKirill Batuzov         }
54253108fb5SKirill Batuzov 
543*3c94193eSAurelien Jarno         /* Simplify expression for "op r, a, a => movi r, 0" cases */
544*3c94193eSAurelien Jarno         switch (op) {
545*3c94193eSAurelien Jarno         CASE_OP_32_64(sub):
546*3c94193eSAurelien Jarno         CASE_OP_32_64(xor):
547*3c94193eSAurelien Jarno             if (temps_are_copies(args[1], args[2])) {
548*3c94193eSAurelien Jarno                 gen_opc_buf[op_index] = op_to_movi(op);
549*3c94193eSAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], 0);
550*3c94193eSAurelien Jarno                 gen_args += 2;
551*3c94193eSAurelien Jarno                 args += 3;
552*3c94193eSAurelien Jarno                 continue;
553*3c94193eSAurelien Jarno             }
554*3c94193eSAurelien Jarno             break;
555*3c94193eSAurelien Jarno         default:
556*3c94193eSAurelien Jarno             break;
557*3c94193eSAurelien Jarno         }
558*3c94193eSAurelien Jarno 
55922613af4SKirill Batuzov         /* Propagate constants through copy operations and do constant
56022613af4SKirill Batuzov            folding.  Constants will be substituted to arguments by register
56122613af4SKirill Batuzov            allocator where needed and possible.  Also detect copies. */
5628f2e8c07SKirill Batuzov         switch (op) {
56322613af4SKirill Batuzov         CASE_OP_32_64(mov):
564e590d4e6SAurelien Jarno             if (temps_are_copies(args[0], args[1])) {
56522613af4SKirill Batuzov                 args += 2;
56622613af4SKirill Batuzov                 gen_opc_buf[op_index] = INDEX_op_nop;
56722613af4SKirill Batuzov                 break;
56822613af4SKirill Batuzov             }
56922613af4SKirill Batuzov             if (temps[args[1]].state != TCG_TEMP_CONST) {
570b80bb016SAurelien Jarno                 tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
57122613af4SKirill Batuzov                 gen_args += 2;
57222613af4SKirill Batuzov                 args += 2;
57322613af4SKirill Batuzov                 break;
57422613af4SKirill Batuzov             }
57522613af4SKirill Batuzov             /* Source argument is constant.  Rewrite the operation and
57622613af4SKirill Batuzov                let movi case handle it. */
57722613af4SKirill Batuzov             op = op_to_movi(op);
57822613af4SKirill Batuzov             gen_opc_buf[op_index] = op;
57922613af4SKirill Batuzov             args[1] = temps[args[1]].val;
58022613af4SKirill Batuzov             /* fallthrough */
58122613af4SKirill Batuzov         CASE_OP_32_64(movi):
582e590d4e6SAurelien Jarno             tcg_opt_gen_movi(gen_args, args[0], args[1]);
58322613af4SKirill Batuzov             gen_args += 2;
58422613af4SKirill Batuzov             args += 2;
58522613af4SKirill Batuzov             break;
586a640f031SKirill Batuzov         CASE_OP_32_64(not):
587cb25c80aSRichard Henderson         CASE_OP_32_64(neg):
58825c4d9ccSRichard Henderson         CASE_OP_32_64(ext8s):
58925c4d9ccSRichard Henderson         CASE_OP_32_64(ext8u):
59025c4d9ccSRichard Henderson         CASE_OP_32_64(ext16s):
59125c4d9ccSRichard Henderson         CASE_OP_32_64(ext16u):
592a640f031SKirill Batuzov         case INDEX_op_ext32s_i64:
593a640f031SKirill Batuzov         case INDEX_op_ext32u_i64:
594a640f031SKirill Batuzov             if (temps[args[1]].state == TCG_TEMP_CONST) {
595a640f031SKirill Batuzov                 gen_opc_buf[op_index] = op_to_movi(op);
596a640f031SKirill Batuzov                 tmp = do_constant_folding(op, temps[args[1]].val, 0);
597e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
598a640f031SKirill Batuzov             } else {
599e590d4e6SAurelien Jarno                 reset_temp(args[0]);
600a640f031SKirill Batuzov                 gen_args[0] = args[0];
601a640f031SKirill Batuzov                 gen_args[1] = args[1];
602fedc0da2SAurelien Jarno             }
603a640f031SKirill Batuzov             gen_args += 2;
604a640f031SKirill Batuzov             args += 2;
605a640f031SKirill Batuzov             break;
60653108fb5SKirill Batuzov         CASE_OP_32_64(add):
60753108fb5SKirill Batuzov         CASE_OP_32_64(sub):
60853108fb5SKirill Batuzov         CASE_OP_32_64(mul):
6099a81090bSKirill Batuzov         CASE_OP_32_64(or):
6109a81090bSKirill Batuzov         CASE_OP_32_64(and):
6119a81090bSKirill Batuzov         CASE_OP_32_64(xor):
61255c0975cSKirill Batuzov         CASE_OP_32_64(shl):
61355c0975cSKirill Batuzov         CASE_OP_32_64(shr):
61455c0975cSKirill Batuzov         CASE_OP_32_64(sar):
61525c4d9ccSRichard Henderson         CASE_OP_32_64(rotl):
61625c4d9ccSRichard Henderson         CASE_OP_32_64(rotr):
617cb25c80aSRichard Henderson         CASE_OP_32_64(andc):
618cb25c80aSRichard Henderson         CASE_OP_32_64(orc):
619cb25c80aSRichard Henderson         CASE_OP_32_64(eqv):
620cb25c80aSRichard Henderson         CASE_OP_32_64(nand):
621cb25c80aSRichard Henderson         CASE_OP_32_64(nor):
62253108fb5SKirill Batuzov             if (temps[args[1]].state == TCG_TEMP_CONST
62353108fb5SKirill Batuzov                 && temps[args[2]].state == TCG_TEMP_CONST) {
62453108fb5SKirill Batuzov                 gen_opc_buf[op_index] = op_to_movi(op);
62553108fb5SKirill Batuzov                 tmp = do_constant_folding(op, temps[args[1]].val,
62653108fb5SKirill Batuzov                                           temps[args[2]].val);
627e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
62853108fb5SKirill Batuzov                 gen_args += 2;
62953108fb5SKirill Batuzov             } else {
630e590d4e6SAurelien Jarno                 reset_temp(args[0]);
63153108fb5SKirill Batuzov                 gen_args[0] = args[0];
63253108fb5SKirill Batuzov                 gen_args[1] = args[1];
63353108fb5SKirill Batuzov                 gen_args[2] = args[2];
63453108fb5SKirill Batuzov                 gen_args += 3;
635fedc0da2SAurelien Jarno             }
63653108fb5SKirill Batuzov             args += 3;
63753108fb5SKirill Batuzov             break;
638f8dd19e5SAurelien Jarno         CASE_OP_32_64(setcond):
639f8dd19e5SAurelien Jarno             if (temps[args[1]].state == TCG_TEMP_CONST
640f8dd19e5SAurelien Jarno                 && temps[args[2]].state == TCG_TEMP_CONST) {
641f8dd19e5SAurelien Jarno                 gen_opc_buf[op_index] = op_to_movi(op);
642f8dd19e5SAurelien Jarno                 tmp = do_constant_folding_cond(op, temps[args[1]].val,
643f8dd19e5SAurelien Jarno                                                temps[args[2]].val, args[3]);
644e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
645f8dd19e5SAurelien Jarno                 gen_args += 2;
646f8dd19e5SAurelien Jarno             } else {
647e590d4e6SAurelien Jarno                 reset_temp(args[0]);
648f8dd19e5SAurelien Jarno                 gen_args[0] = args[0];
649f8dd19e5SAurelien Jarno                 gen_args[1] = args[1];
650f8dd19e5SAurelien Jarno                 gen_args[2] = args[2];
651f8dd19e5SAurelien Jarno                 gen_args[3] = args[3];
652f8dd19e5SAurelien Jarno                 gen_args += 4;
653fedc0da2SAurelien Jarno             }
654f8dd19e5SAurelien Jarno             args += 4;
655f8dd19e5SAurelien Jarno             break;
656fbeaa26cSAurelien Jarno         CASE_OP_32_64(brcond):
657fbeaa26cSAurelien Jarno             if (temps[args[0]].state == TCG_TEMP_CONST
658fbeaa26cSAurelien Jarno                 && temps[args[1]].state == TCG_TEMP_CONST) {
659fbeaa26cSAurelien Jarno                 if (do_constant_folding_cond(op, temps[args[0]].val,
660fbeaa26cSAurelien Jarno                                              temps[args[1]].val, args[2])) {
661fbeaa26cSAurelien Jarno                     memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
662fbeaa26cSAurelien Jarno                     gen_opc_buf[op_index] = INDEX_op_br;
663fbeaa26cSAurelien Jarno                     gen_args[0] = args[3];
664fbeaa26cSAurelien Jarno                     gen_args += 1;
665fbeaa26cSAurelien Jarno                 } else {
666fbeaa26cSAurelien Jarno                     gen_opc_buf[op_index] = INDEX_op_nop;
667fbeaa26cSAurelien Jarno                 }
668fbeaa26cSAurelien Jarno             } else {
669fbeaa26cSAurelien Jarno                 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
670e590d4e6SAurelien Jarno                 reset_temp(args[0]);
671fbeaa26cSAurelien Jarno                 gen_args[0] = args[0];
672fbeaa26cSAurelien Jarno                 gen_args[1] = args[1];
673fbeaa26cSAurelien Jarno                 gen_args[2] = args[2];
674fbeaa26cSAurelien Jarno                 gen_args[3] = args[3];
675fbeaa26cSAurelien Jarno                 gen_args += 4;
676fedc0da2SAurelien Jarno             }
677fbeaa26cSAurelien Jarno             args += 4;
678fbeaa26cSAurelien Jarno             break;
679fa01a208SRichard Henderson         CASE_OP_32_64(movcond):
680fa01a208SRichard Henderson             if (temps[args[1]].state == TCG_TEMP_CONST
681fa01a208SRichard Henderson                 && temps[args[2]].state == TCG_TEMP_CONST) {
682fa01a208SRichard Henderson                 tmp = do_constant_folding_cond(op, temps[args[1]].val,
683fa01a208SRichard Henderson                                                temps[args[2]].val, args[5]);
684e590d4e6SAurelien Jarno                 if (temps_are_copies(args[0], args[4-tmp])) {
685fa01a208SRichard Henderson                     gen_opc_buf[op_index] = INDEX_op_nop;
686fa01a208SRichard Henderson                 } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
687fa01a208SRichard Henderson                     gen_opc_buf[op_index] = op_to_movi(op);
688e590d4e6SAurelien Jarno                     tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
689fa01a208SRichard Henderson                     gen_args += 2;
690fa01a208SRichard Henderson                 } else {
691fa01a208SRichard Henderson                     gen_opc_buf[op_index] = op_to_mov(op);
692e590d4e6SAurelien Jarno                     tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
693fa01a208SRichard Henderson                     gen_args += 2;
694fa01a208SRichard Henderson                 }
695fa01a208SRichard Henderson             } else {
696e590d4e6SAurelien Jarno                 reset_temp(args[0]);
697fa01a208SRichard Henderson                 gen_args[0] = args[0];
698fa01a208SRichard Henderson                 gen_args[1] = args[1];
699fa01a208SRichard Henderson                 gen_args[2] = args[2];
700fa01a208SRichard Henderson                 gen_args[3] = args[3];
701fa01a208SRichard Henderson                 gen_args[4] = args[4];
702fa01a208SRichard Henderson                 gen_args[5] = args[5];
703fa01a208SRichard Henderson                 gen_args += 6;
704fa01a208SRichard Henderson             }
705fa01a208SRichard Henderson             args += 6;
706fa01a208SRichard Henderson             break;
7078f2e8c07SKirill Batuzov         case INDEX_op_call:
70822613af4SKirill Batuzov             nb_call_args = (args[0] >> 16) + (args[0] & 0xffff);
70922613af4SKirill Batuzov             if (!(args[nb_call_args + 1] & (TCG_CALL_CONST | TCG_CALL_PURE))) {
71022613af4SKirill Batuzov                 for (i = 0; i < nb_globals; i++) {
711e590d4e6SAurelien Jarno                     reset_temp(i);
71222613af4SKirill Batuzov                 }
71322613af4SKirill Batuzov             }
71422613af4SKirill Batuzov             for (i = 0; i < (args[0] >> 16); i++) {
715e590d4e6SAurelien Jarno                 reset_temp(args[i + 1]);
71622613af4SKirill Batuzov             }
71722613af4SKirill Batuzov             i = nb_call_args + 3;
7188f2e8c07SKirill Batuzov             while (i) {
7198f2e8c07SKirill Batuzov                 *gen_args = *args;
7208f2e8c07SKirill Batuzov                 args++;
7218f2e8c07SKirill Batuzov                 gen_args++;
7228f2e8c07SKirill Batuzov                 i--;
7238f2e8c07SKirill Batuzov             }
7248f2e8c07SKirill Batuzov             break;
7258f2e8c07SKirill Batuzov         default:
72622613af4SKirill Batuzov             /* Default case: we do know nothing about operation so no
727a2550660SAurelien Jarno                propagation is done.  We trash everything if the operation
728a2550660SAurelien Jarno                is the end of a basic block, otherwise we only trash the
729a2550660SAurelien Jarno                output args.  */
730a2550660SAurelien Jarno             if (def->flags & TCG_OPF_BB_END) {
731a2550660SAurelien Jarno                 memset(temps, 0, nb_temps * sizeof(struct tcg_temp_info));
732a2550660SAurelien Jarno             } else {
73322613af4SKirill Batuzov                 for (i = 0; i < def->nb_oargs; i++) {
734e590d4e6SAurelien Jarno                     reset_temp(args[i]);
73522613af4SKirill Batuzov                 }
736a2550660SAurelien Jarno             }
7378f2e8c07SKirill Batuzov             for (i = 0; i < def->nb_args; i++) {
7388f2e8c07SKirill Batuzov                 gen_args[i] = args[i];
7398f2e8c07SKirill Batuzov             }
7408f2e8c07SKirill Batuzov             args += def->nb_args;
7418f2e8c07SKirill Batuzov             gen_args += def->nb_args;
7428f2e8c07SKirill Batuzov             break;
7438f2e8c07SKirill Batuzov         }
7448f2e8c07SKirill Batuzov     }
7458f2e8c07SKirill Batuzov 
7468f2e8c07SKirill Batuzov     return gen_args;
7478f2e8c07SKirill Batuzov }
7488f2e8c07SKirill Batuzov 
7498f2e8c07SKirill Batuzov TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
7508f2e8c07SKirill Batuzov         TCGArg *args, TCGOpDef *tcg_op_defs)
7518f2e8c07SKirill Batuzov {
7528f2e8c07SKirill Batuzov     TCGArg *res;
7538f2e8c07SKirill Batuzov     res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
7548f2e8c07SKirill Batuzov     return res;
7558f2e8c07SKirill Batuzov }
756