xref: /openbmc/qemu/tcg/optimize.c (revision cf066674)
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;
493a9d8b17SPaolo Bonzini     tcg_target_ulong mask;
5022613af4SKirill Batuzov };
5122613af4SKirill Batuzov 
5222613af4SKirill Batuzov static struct tcg_temp_info temps[TCG_MAX_TEMPS];
5322613af4SKirill Batuzov 
54e590d4e6SAurelien Jarno /* Reset TEMP's state to TCG_TEMP_UNDEF.  If TEMP only had one copy, remove
55e590d4e6SAurelien Jarno    the copy flag from the left temp.  */
56e590d4e6SAurelien Jarno static void reset_temp(TCGArg temp)
5722613af4SKirill Batuzov {
58e590d4e6SAurelien Jarno     if (temps[temp].state == TCG_TEMP_COPY) {
59e590d4e6SAurelien Jarno         if (temps[temp].prev_copy == temps[temp].next_copy) {
60e590d4e6SAurelien Jarno             temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF;
6122613af4SKirill Batuzov         } else {
6222613af4SKirill Batuzov             temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
6322613af4SKirill Batuzov             temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
64e590d4e6SAurelien Jarno         }
6522613af4SKirill Batuzov     }
6648b56ce1SAurelien Jarno     temps[temp].state = TCG_TEMP_UNDEF;
673a9d8b17SPaolo Bonzini     temps[temp].mask = -1;
6822613af4SKirill Batuzov }
6922613af4SKirill Batuzov 
70d193a14aSPaolo Bonzini /* Reset all temporaries, given that there are NB_TEMPS of them.  */
71d193a14aSPaolo Bonzini static void reset_all_temps(int nb_temps)
72d193a14aSPaolo Bonzini {
73d193a14aSPaolo Bonzini     int i;
74d193a14aSPaolo Bonzini     for (i = 0; i < nb_temps; i++) {
75d193a14aSPaolo Bonzini         temps[i].state = TCG_TEMP_UNDEF;
763a9d8b17SPaolo Bonzini         temps[i].mask = -1;
77d193a14aSPaolo Bonzini     }
78d193a14aSPaolo Bonzini }
79d193a14aSPaolo Bonzini 
80fe0de7aaSBlue Swirl static int op_bits(TCGOpcode op)
8122613af4SKirill Batuzov {
828399ad59SRichard Henderson     const TCGOpDef *def = &tcg_op_defs[op];
838399ad59SRichard Henderson     return def->flags & TCG_OPF_64BIT ? 64 : 32;
8422613af4SKirill Batuzov }
8522613af4SKirill Batuzov 
86fe0de7aaSBlue Swirl static TCGOpcode op_to_movi(TCGOpcode op)
8722613af4SKirill Batuzov {
8822613af4SKirill Batuzov     switch (op_bits(op)) {
8922613af4SKirill Batuzov     case 32:
9022613af4SKirill Batuzov         return INDEX_op_movi_i32;
9122613af4SKirill Batuzov     case 64:
9222613af4SKirill Batuzov         return INDEX_op_movi_i64;
9322613af4SKirill Batuzov     default:
9422613af4SKirill Batuzov         fprintf(stderr, "op_to_movi: unexpected return value of "
9522613af4SKirill Batuzov                 "function op_bits.\n");
9622613af4SKirill Batuzov         tcg_abort();
9722613af4SKirill Batuzov     }
9822613af4SKirill Batuzov }
9922613af4SKirill Batuzov 
100e590d4e6SAurelien Jarno static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
101e590d4e6SAurelien Jarno {
102e590d4e6SAurelien Jarno     TCGArg i;
103e590d4e6SAurelien Jarno 
104e590d4e6SAurelien Jarno     /* If this is already a global, we can't do better. */
105e590d4e6SAurelien Jarno     if (temp < s->nb_globals) {
106e590d4e6SAurelien Jarno         return temp;
107e590d4e6SAurelien Jarno     }
108e590d4e6SAurelien Jarno 
109e590d4e6SAurelien Jarno     /* Search for a global first. */
110e590d4e6SAurelien Jarno     for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
111e590d4e6SAurelien Jarno         if (i < s->nb_globals) {
112e590d4e6SAurelien Jarno             return i;
113e590d4e6SAurelien Jarno         }
114e590d4e6SAurelien Jarno     }
115e590d4e6SAurelien Jarno 
116e590d4e6SAurelien Jarno     /* If it is a temp, search for a temp local. */
117e590d4e6SAurelien Jarno     if (!s->temps[temp].temp_local) {
118e590d4e6SAurelien Jarno         for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
119e590d4e6SAurelien Jarno             if (s->temps[i].temp_local) {
120e590d4e6SAurelien Jarno                 return i;
121e590d4e6SAurelien Jarno             }
122e590d4e6SAurelien Jarno         }
123e590d4e6SAurelien Jarno     }
124e590d4e6SAurelien Jarno 
125e590d4e6SAurelien Jarno     /* Failure to find a better representation, return the same temp. */
126e590d4e6SAurelien Jarno     return temp;
127e590d4e6SAurelien Jarno }
128e590d4e6SAurelien Jarno 
129e590d4e6SAurelien Jarno static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
130e590d4e6SAurelien Jarno {
131e590d4e6SAurelien Jarno     TCGArg i;
132e590d4e6SAurelien Jarno 
133e590d4e6SAurelien Jarno     if (arg1 == arg2) {
134e590d4e6SAurelien Jarno         return true;
135e590d4e6SAurelien Jarno     }
136e590d4e6SAurelien Jarno 
137e590d4e6SAurelien Jarno     if (temps[arg1].state != TCG_TEMP_COPY
138e590d4e6SAurelien Jarno         || temps[arg2].state != TCG_TEMP_COPY) {
139e590d4e6SAurelien Jarno         return false;
140e590d4e6SAurelien Jarno     }
141e590d4e6SAurelien Jarno 
142e590d4e6SAurelien Jarno     for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
143e590d4e6SAurelien Jarno         if (i == arg2) {
144e590d4e6SAurelien Jarno             return true;
145e590d4e6SAurelien Jarno         }
146e590d4e6SAurelien Jarno     }
147e590d4e6SAurelien Jarno 
148e590d4e6SAurelien Jarno     return false;
149e590d4e6SAurelien Jarno }
150e590d4e6SAurelien Jarno 
151b80bb016SAurelien Jarno static void tcg_opt_gen_mov(TCGContext *s, TCGArg *gen_args,
152b80bb016SAurelien Jarno                             TCGArg dst, TCGArg src)
15322613af4SKirill Batuzov {
154e590d4e6SAurelien Jarno     reset_temp(dst);
1553a9d8b17SPaolo Bonzini     temps[dst].mask = temps[src].mask;
15622613af4SKirill Batuzov     assert(temps[src].state != TCG_TEMP_CONST);
157e590d4e6SAurelien Jarno 
158e590d4e6SAurelien Jarno     if (s->temps[src].type == s->temps[dst].type) {
159e590d4e6SAurelien Jarno         if (temps[src].state != TCG_TEMP_COPY) {
160e590d4e6SAurelien Jarno             temps[src].state = TCG_TEMP_COPY;
16122613af4SKirill Batuzov             temps[src].next_copy = src;
16222613af4SKirill Batuzov             temps[src].prev_copy = src;
16322613af4SKirill Batuzov         }
16422613af4SKirill Batuzov         temps[dst].state = TCG_TEMP_COPY;
16522613af4SKirill Batuzov         temps[dst].next_copy = temps[src].next_copy;
16622613af4SKirill Batuzov         temps[dst].prev_copy = src;
16722613af4SKirill Batuzov         temps[temps[dst].next_copy].prev_copy = dst;
16822613af4SKirill Batuzov         temps[src].next_copy = dst;
16922613af4SKirill Batuzov     }
170e590d4e6SAurelien Jarno 
17122613af4SKirill Batuzov     gen_args[0] = dst;
17222613af4SKirill Batuzov     gen_args[1] = src;
17322613af4SKirill Batuzov }
17422613af4SKirill Batuzov 
175e590d4e6SAurelien Jarno static void tcg_opt_gen_movi(TCGArg *gen_args, TCGArg dst, TCGArg val)
17622613af4SKirill Batuzov {
177e590d4e6SAurelien Jarno     reset_temp(dst);
17822613af4SKirill Batuzov     temps[dst].state = TCG_TEMP_CONST;
17922613af4SKirill Batuzov     temps[dst].val = val;
1803a9d8b17SPaolo Bonzini     temps[dst].mask = val;
18122613af4SKirill Batuzov     gen_args[0] = dst;
18222613af4SKirill Batuzov     gen_args[1] = val;
18322613af4SKirill Batuzov }
18422613af4SKirill Batuzov 
185fe0de7aaSBlue Swirl static TCGOpcode op_to_mov(TCGOpcode op)
18653108fb5SKirill Batuzov {
18753108fb5SKirill Batuzov     switch (op_bits(op)) {
18853108fb5SKirill Batuzov     case 32:
18953108fb5SKirill Batuzov         return INDEX_op_mov_i32;
19053108fb5SKirill Batuzov     case 64:
19153108fb5SKirill Batuzov         return INDEX_op_mov_i64;
19253108fb5SKirill Batuzov     default:
19353108fb5SKirill Batuzov         fprintf(stderr, "op_to_mov: unexpected return value of "
19453108fb5SKirill Batuzov                 "function op_bits.\n");
19553108fb5SKirill Batuzov         tcg_abort();
19653108fb5SKirill Batuzov     }
19753108fb5SKirill Batuzov }
19853108fb5SKirill Batuzov 
199fe0de7aaSBlue Swirl static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
20053108fb5SKirill Batuzov {
20103271524SRichard Henderson     uint64_t l64, h64;
20203271524SRichard Henderson 
20353108fb5SKirill Batuzov     switch (op) {
20453108fb5SKirill Batuzov     CASE_OP_32_64(add):
20553108fb5SKirill Batuzov         return x + y;
20653108fb5SKirill Batuzov 
20753108fb5SKirill Batuzov     CASE_OP_32_64(sub):
20853108fb5SKirill Batuzov         return x - y;
20953108fb5SKirill Batuzov 
21053108fb5SKirill Batuzov     CASE_OP_32_64(mul):
21153108fb5SKirill Batuzov         return x * y;
21253108fb5SKirill Batuzov 
2139a81090bSKirill Batuzov     CASE_OP_32_64(and):
2149a81090bSKirill Batuzov         return x & y;
2159a81090bSKirill Batuzov 
2169a81090bSKirill Batuzov     CASE_OP_32_64(or):
2179a81090bSKirill Batuzov         return x | y;
2189a81090bSKirill Batuzov 
2199a81090bSKirill Batuzov     CASE_OP_32_64(xor):
2209a81090bSKirill Batuzov         return x ^ y;
2219a81090bSKirill Batuzov 
22255c0975cSKirill Batuzov     case INDEX_op_shl_i32:
22350c5c4d1SRichard Henderson         return (uint32_t)x << (y & 31);
22455c0975cSKirill Batuzov 
22555c0975cSKirill Batuzov     case INDEX_op_shl_i64:
22650c5c4d1SRichard Henderson         return (uint64_t)x << (y & 63);
22755c0975cSKirill Batuzov 
22855c0975cSKirill Batuzov     case INDEX_op_shr_i32:
22950c5c4d1SRichard Henderson         return (uint32_t)x >> (y & 31);
23055c0975cSKirill Batuzov 
2314bb7a41eSRichard Henderson     case INDEX_op_trunc_shr_i32:
23255c0975cSKirill Batuzov     case INDEX_op_shr_i64:
23350c5c4d1SRichard Henderson         return (uint64_t)x >> (y & 63);
23455c0975cSKirill Batuzov 
23555c0975cSKirill Batuzov     case INDEX_op_sar_i32:
23650c5c4d1SRichard Henderson         return (int32_t)x >> (y & 31);
23755c0975cSKirill Batuzov 
23855c0975cSKirill Batuzov     case INDEX_op_sar_i64:
23950c5c4d1SRichard Henderson         return (int64_t)x >> (y & 63);
24055c0975cSKirill Batuzov 
24155c0975cSKirill Batuzov     case INDEX_op_rotr_i32:
24250c5c4d1SRichard Henderson         return ror32(x, y & 31);
24355c0975cSKirill Batuzov 
24455c0975cSKirill Batuzov     case INDEX_op_rotr_i64:
24550c5c4d1SRichard Henderson         return ror64(x, y & 63);
24655c0975cSKirill Batuzov 
24755c0975cSKirill Batuzov     case INDEX_op_rotl_i32:
24850c5c4d1SRichard Henderson         return rol32(x, y & 31);
24955c0975cSKirill Batuzov 
25055c0975cSKirill Batuzov     case INDEX_op_rotl_i64:
25150c5c4d1SRichard Henderson         return rol64(x, y & 63);
25255c0975cSKirill Batuzov 
25325c4d9ccSRichard Henderson     CASE_OP_32_64(not):
254a640f031SKirill Batuzov         return ~x;
255a640f031SKirill Batuzov 
256cb25c80aSRichard Henderson     CASE_OP_32_64(neg):
257cb25c80aSRichard Henderson         return -x;
258cb25c80aSRichard Henderson 
259cb25c80aSRichard Henderson     CASE_OP_32_64(andc):
260cb25c80aSRichard Henderson         return x & ~y;
261cb25c80aSRichard Henderson 
262cb25c80aSRichard Henderson     CASE_OP_32_64(orc):
263cb25c80aSRichard Henderson         return x | ~y;
264cb25c80aSRichard Henderson 
265cb25c80aSRichard Henderson     CASE_OP_32_64(eqv):
266cb25c80aSRichard Henderson         return ~(x ^ y);
267cb25c80aSRichard Henderson 
268cb25c80aSRichard Henderson     CASE_OP_32_64(nand):
269cb25c80aSRichard Henderson         return ~(x & y);
270cb25c80aSRichard Henderson 
271cb25c80aSRichard Henderson     CASE_OP_32_64(nor):
272cb25c80aSRichard Henderson         return ~(x | y);
273cb25c80aSRichard Henderson 
27425c4d9ccSRichard Henderson     CASE_OP_32_64(ext8s):
275a640f031SKirill Batuzov         return (int8_t)x;
276a640f031SKirill Batuzov 
27725c4d9ccSRichard Henderson     CASE_OP_32_64(ext16s):
278a640f031SKirill Batuzov         return (int16_t)x;
279a640f031SKirill Batuzov 
28025c4d9ccSRichard Henderson     CASE_OP_32_64(ext8u):
281a640f031SKirill Batuzov         return (uint8_t)x;
282a640f031SKirill Batuzov 
28325c4d9ccSRichard Henderson     CASE_OP_32_64(ext16u):
284a640f031SKirill Batuzov         return (uint16_t)x;
285a640f031SKirill Batuzov 
286a640f031SKirill Batuzov     case INDEX_op_ext32s_i64:
287a640f031SKirill Batuzov         return (int32_t)x;
288a640f031SKirill Batuzov 
289a640f031SKirill Batuzov     case INDEX_op_ext32u_i64:
290a640f031SKirill Batuzov         return (uint32_t)x;
291a640f031SKirill Batuzov 
29203271524SRichard Henderson     case INDEX_op_muluh_i32:
29303271524SRichard Henderson         return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
29403271524SRichard Henderson     case INDEX_op_mulsh_i32:
29503271524SRichard Henderson         return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
29603271524SRichard Henderson 
29703271524SRichard Henderson     case INDEX_op_muluh_i64:
29803271524SRichard Henderson         mulu64(&l64, &h64, x, y);
29903271524SRichard Henderson         return h64;
30003271524SRichard Henderson     case INDEX_op_mulsh_i64:
30103271524SRichard Henderson         muls64(&l64, &h64, x, y);
30203271524SRichard Henderson         return h64;
30303271524SRichard Henderson 
30401547f7fSRichard Henderson     case INDEX_op_div_i32:
30501547f7fSRichard Henderson         /* Avoid crashing on divide by zero, otherwise undefined.  */
30601547f7fSRichard Henderson         return (int32_t)x / ((int32_t)y ? : 1);
30701547f7fSRichard Henderson     case INDEX_op_divu_i32:
30801547f7fSRichard Henderson         return (uint32_t)x / ((uint32_t)y ? : 1);
30901547f7fSRichard Henderson     case INDEX_op_div_i64:
31001547f7fSRichard Henderson         return (int64_t)x / ((int64_t)y ? : 1);
31101547f7fSRichard Henderson     case INDEX_op_divu_i64:
31201547f7fSRichard Henderson         return (uint64_t)x / ((uint64_t)y ? : 1);
31301547f7fSRichard Henderson 
31401547f7fSRichard Henderson     case INDEX_op_rem_i32:
31501547f7fSRichard Henderson         return (int32_t)x % ((int32_t)y ? : 1);
31601547f7fSRichard Henderson     case INDEX_op_remu_i32:
31701547f7fSRichard Henderson         return (uint32_t)x % ((uint32_t)y ? : 1);
31801547f7fSRichard Henderson     case INDEX_op_rem_i64:
31901547f7fSRichard Henderson         return (int64_t)x % ((int64_t)y ? : 1);
32001547f7fSRichard Henderson     case INDEX_op_remu_i64:
32101547f7fSRichard Henderson         return (uint64_t)x % ((uint64_t)y ? : 1);
32201547f7fSRichard Henderson 
32353108fb5SKirill Batuzov     default:
32453108fb5SKirill Batuzov         fprintf(stderr,
32553108fb5SKirill Batuzov                 "Unrecognized operation %d in do_constant_folding.\n", op);
32653108fb5SKirill Batuzov         tcg_abort();
32753108fb5SKirill Batuzov     }
32853108fb5SKirill Batuzov }
32953108fb5SKirill Batuzov 
330fe0de7aaSBlue Swirl static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
33153108fb5SKirill Batuzov {
33253108fb5SKirill Batuzov     TCGArg res = do_constant_folding_2(op, x, y);
33353108fb5SKirill Batuzov     if (op_bits(op) == 32) {
33453108fb5SKirill Batuzov         res &= 0xffffffff;
33553108fb5SKirill Batuzov     }
33653108fb5SKirill Batuzov     return res;
33753108fb5SKirill Batuzov }
33853108fb5SKirill Batuzov 
3399519da7eSRichard Henderson static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
340f8dd19e5SAurelien Jarno {
341f8dd19e5SAurelien Jarno     switch (c) {
342f8dd19e5SAurelien Jarno     case TCG_COND_EQ:
3439519da7eSRichard Henderson         return x == y;
344f8dd19e5SAurelien Jarno     case TCG_COND_NE:
3459519da7eSRichard Henderson         return x != y;
346f8dd19e5SAurelien Jarno     case TCG_COND_LT:
3479519da7eSRichard Henderson         return (int32_t)x < (int32_t)y;
348f8dd19e5SAurelien Jarno     case TCG_COND_GE:
3499519da7eSRichard Henderson         return (int32_t)x >= (int32_t)y;
350f8dd19e5SAurelien Jarno     case TCG_COND_LE:
3519519da7eSRichard Henderson         return (int32_t)x <= (int32_t)y;
352f8dd19e5SAurelien Jarno     case TCG_COND_GT:
3539519da7eSRichard Henderson         return (int32_t)x > (int32_t)y;
354f8dd19e5SAurelien Jarno     case TCG_COND_LTU:
3559519da7eSRichard Henderson         return x < y;
356f8dd19e5SAurelien Jarno     case TCG_COND_GEU:
3579519da7eSRichard Henderson         return x >= y;
358f8dd19e5SAurelien Jarno     case TCG_COND_LEU:
3599519da7eSRichard Henderson         return x <= y;
360f8dd19e5SAurelien Jarno     case TCG_COND_GTU:
3619519da7eSRichard Henderson         return x > y;
3620aed257fSRichard Henderson     default:
3639519da7eSRichard Henderson         tcg_abort();
364f8dd19e5SAurelien Jarno     }
3659519da7eSRichard Henderson }
3669519da7eSRichard Henderson 
3679519da7eSRichard Henderson static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
3689519da7eSRichard Henderson {
369f8dd19e5SAurelien Jarno     switch (c) {
370f8dd19e5SAurelien Jarno     case TCG_COND_EQ:
3719519da7eSRichard Henderson         return x == y;
372f8dd19e5SAurelien Jarno     case TCG_COND_NE:
3739519da7eSRichard Henderson         return x != y;
374f8dd19e5SAurelien Jarno     case TCG_COND_LT:
3759519da7eSRichard Henderson         return (int64_t)x < (int64_t)y;
376f8dd19e5SAurelien Jarno     case TCG_COND_GE:
3779519da7eSRichard Henderson         return (int64_t)x >= (int64_t)y;
378f8dd19e5SAurelien Jarno     case TCG_COND_LE:
3799519da7eSRichard Henderson         return (int64_t)x <= (int64_t)y;
380f8dd19e5SAurelien Jarno     case TCG_COND_GT:
3819519da7eSRichard Henderson         return (int64_t)x > (int64_t)y;
382f8dd19e5SAurelien Jarno     case TCG_COND_LTU:
3839519da7eSRichard Henderson         return x < y;
384f8dd19e5SAurelien Jarno     case TCG_COND_GEU:
3859519da7eSRichard Henderson         return x >= y;
386f8dd19e5SAurelien Jarno     case TCG_COND_LEU:
3879519da7eSRichard Henderson         return x <= y;
388f8dd19e5SAurelien Jarno     case TCG_COND_GTU:
3899519da7eSRichard Henderson         return x > y;
3900aed257fSRichard Henderson     default:
3919519da7eSRichard Henderson         tcg_abort();
392f8dd19e5SAurelien Jarno     }
393f8dd19e5SAurelien Jarno }
3949519da7eSRichard Henderson 
3959519da7eSRichard Henderson static bool do_constant_folding_cond_eq(TCGCond c)
3969519da7eSRichard Henderson {
397b336ceb6SAurelien Jarno     switch (c) {
398b336ceb6SAurelien Jarno     case TCG_COND_GT:
399b336ceb6SAurelien Jarno     case TCG_COND_LTU:
400b336ceb6SAurelien Jarno     case TCG_COND_LT:
401b336ceb6SAurelien Jarno     case TCG_COND_GTU:
402b336ceb6SAurelien Jarno     case TCG_COND_NE:
403b336ceb6SAurelien Jarno         return 0;
404b336ceb6SAurelien Jarno     case TCG_COND_GE:
405b336ceb6SAurelien Jarno     case TCG_COND_GEU:
406b336ceb6SAurelien Jarno     case TCG_COND_LE:
407b336ceb6SAurelien Jarno     case TCG_COND_LEU:
408b336ceb6SAurelien Jarno     case TCG_COND_EQ:
409b336ceb6SAurelien Jarno         return 1;
4100aed257fSRichard Henderson     default:
4119519da7eSRichard Henderson         tcg_abort();
412b336ceb6SAurelien Jarno     }
4139519da7eSRichard Henderson }
4149519da7eSRichard Henderson 
4159519da7eSRichard Henderson /* Return 2 if the condition can't be simplified, and the result
4169519da7eSRichard Henderson    of the condition (0 or 1) if it can */
4179519da7eSRichard Henderson static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
4189519da7eSRichard Henderson                                        TCGArg y, TCGCond c)
4199519da7eSRichard Henderson {
4209519da7eSRichard Henderson     if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) {
4219519da7eSRichard Henderson         switch (op_bits(op)) {
4229519da7eSRichard Henderson         case 32:
4239519da7eSRichard Henderson             return do_constant_folding_cond_32(temps[x].val, temps[y].val, c);
4249519da7eSRichard Henderson         case 64:
4259519da7eSRichard Henderson             return do_constant_folding_cond_64(temps[x].val, temps[y].val, c);
4269519da7eSRichard Henderson         default:
4279519da7eSRichard Henderson             tcg_abort();
4289519da7eSRichard Henderson         }
4299519da7eSRichard Henderson     } else if (temps_are_copies(x, y)) {
4309519da7eSRichard Henderson         return do_constant_folding_cond_eq(c);
431b336ceb6SAurelien Jarno     } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) {
432b336ceb6SAurelien Jarno         switch (c) {
433b336ceb6SAurelien Jarno         case TCG_COND_LTU:
434b336ceb6SAurelien Jarno             return 0;
435b336ceb6SAurelien Jarno         case TCG_COND_GEU:
436b336ceb6SAurelien Jarno             return 1;
437b336ceb6SAurelien Jarno         default:
438b336ceb6SAurelien Jarno             return 2;
439b336ceb6SAurelien Jarno         }
440b336ceb6SAurelien Jarno     } else {
441b336ceb6SAurelien Jarno         return 2;
442b336ceb6SAurelien Jarno     }
443f8dd19e5SAurelien Jarno }
444f8dd19e5SAurelien Jarno 
4456c4382f8SRichard Henderson /* Return 2 if the condition can't be simplified, and the result
4466c4382f8SRichard Henderson    of the condition (0 or 1) if it can */
4476c4382f8SRichard Henderson static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
4486c4382f8SRichard Henderson {
4496c4382f8SRichard Henderson     TCGArg al = p1[0], ah = p1[1];
4506c4382f8SRichard Henderson     TCGArg bl = p2[0], bh = p2[1];
4516c4382f8SRichard Henderson 
4526c4382f8SRichard Henderson     if (temps[bl].state == TCG_TEMP_CONST
4536c4382f8SRichard Henderson         && temps[bh].state == TCG_TEMP_CONST) {
4546c4382f8SRichard Henderson         uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val;
4556c4382f8SRichard Henderson 
4566c4382f8SRichard Henderson         if (temps[al].state == TCG_TEMP_CONST
4576c4382f8SRichard Henderson             && temps[ah].state == TCG_TEMP_CONST) {
4586c4382f8SRichard Henderson             uint64_t a;
4596c4382f8SRichard Henderson             a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val;
4606c4382f8SRichard Henderson             return do_constant_folding_cond_64(a, b, c);
4616c4382f8SRichard Henderson         }
4626c4382f8SRichard Henderson         if (b == 0) {
4636c4382f8SRichard Henderson             switch (c) {
4646c4382f8SRichard Henderson             case TCG_COND_LTU:
4656c4382f8SRichard Henderson                 return 0;
4666c4382f8SRichard Henderson             case TCG_COND_GEU:
4676c4382f8SRichard Henderson                 return 1;
4686c4382f8SRichard Henderson             default:
4696c4382f8SRichard Henderson                 break;
4706c4382f8SRichard Henderson             }
4716c4382f8SRichard Henderson         }
4726c4382f8SRichard Henderson     }
4736c4382f8SRichard Henderson     if (temps_are_copies(al, bl) && temps_are_copies(ah, bh)) {
4746c4382f8SRichard Henderson         return do_constant_folding_cond_eq(c);
4756c4382f8SRichard Henderson     }
4766c4382f8SRichard Henderson     return 2;
4776c4382f8SRichard Henderson }
4786c4382f8SRichard Henderson 
47924c9ae4eSRichard Henderson static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
48024c9ae4eSRichard Henderson {
48124c9ae4eSRichard Henderson     TCGArg a1 = *p1, a2 = *p2;
48224c9ae4eSRichard Henderson     int sum = 0;
48324c9ae4eSRichard Henderson     sum += temps[a1].state == TCG_TEMP_CONST;
48424c9ae4eSRichard Henderson     sum -= temps[a2].state == TCG_TEMP_CONST;
48524c9ae4eSRichard Henderson 
48624c9ae4eSRichard Henderson     /* Prefer the constant in second argument, and then the form
48724c9ae4eSRichard Henderson        op a, a, b, which is better handled on non-RISC hosts. */
48824c9ae4eSRichard Henderson     if (sum > 0 || (sum == 0 && dest == a2)) {
48924c9ae4eSRichard Henderson         *p1 = a2;
49024c9ae4eSRichard Henderson         *p2 = a1;
49124c9ae4eSRichard Henderson         return true;
49224c9ae4eSRichard Henderson     }
49324c9ae4eSRichard Henderson     return false;
49424c9ae4eSRichard Henderson }
49524c9ae4eSRichard Henderson 
4960bfcb865SRichard Henderson static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
4970bfcb865SRichard Henderson {
4980bfcb865SRichard Henderson     int sum = 0;
4990bfcb865SRichard Henderson     sum += temps[p1[0]].state == TCG_TEMP_CONST;
5000bfcb865SRichard Henderson     sum += temps[p1[1]].state == TCG_TEMP_CONST;
5010bfcb865SRichard Henderson     sum -= temps[p2[0]].state == TCG_TEMP_CONST;
5020bfcb865SRichard Henderson     sum -= temps[p2[1]].state == TCG_TEMP_CONST;
5030bfcb865SRichard Henderson     if (sum > 0) {
5040bfcb865SRichard Henderson         TCGArg t;
5050bfcb865SRichard Henderson         t = p1[0], p1[0] = p2[0], p2[0] = t;
5060bfcb865SRichard Henderson         t = p1[1], p1[1] = p2[1], p2[1] = t;
5070bfcb865SRichard Henderson         return true;
5080bfcb865SRichard Henderson     }
5090bfcb865SRichard Henderson     return false;
5100bfcb865SRichard Henderson }
5110bfcb865SRichard Henderson 
51222613af4SKirill Batuzov /* Propagate constants and copies, fold constant expressions. */
5138f2e8c07SKirill Batuzov static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr,
5148f2e8c07SKirill Batuzov                                     TCGArg *args, TCGOpDef *tcg_op_defs)
5158f2e8c07SKirill Batuzov {
516*cf066674SRichard Henderson     int nb_ops, op_index, nb_temps, nb_globals;
5178f2e8c07SKirill Batuzov     TCGArg *gen_args;
5185d8f5363SRichard Henderson 
51922613af4SKirill Batuzov     /* Array VALS has an element for each temp.
52022613af4SKirill Batuzov        If this temp holds a constant then its value is kept in VALS' element.
521e590d4e6SAurelien Jarno        If this temp is a copy of other ones then the other copies are
522e590d4e6SAurelien Jarno        available through the doubly linked circular list. */
5238f2e8c07SKirill Batuzov 
5248f2e8c07SKirill Batuzov     nb_temps = s->nb_temps;
5258f2e8c07SKirill Batuzov     nb_globals = s->nb_globals;
526d193a14aSPaolo Bonzini     reset_all_temps(nb_temps);
5278f2e8c07SKirill Batuzov 
52892414b31SEvgeny Voevodin     nb_ops = tcg_opc_ptr - s->gen_opc_buf;
5298f2e8c07SKirill Batuzov     gen_args = args;
5308f2e8c07SKirill Batuzov     for (op_index = 0; op_index < nb_ops; op_index++) {
531*cf066674SRichard Henderson         TCGOpcode op = s->gen_opc_buf[op_index];
532*cf066674SRichard Henderson         const TCGOpDef *def = &tcg_op_defs[op];
533*cf066674SRichard Henderson         tcg_target_ulong mask, affected;
534*cf066674SRichard Henderson         int nb_oargs, nb_iargs, nb_args, i;
535*cf066674SRichard Henderson         TCGArg tmp;
536*cf066674SRichard Henderson 
5371ff8c541SAurelien Jarno         if (op == INDEX_op_call) {
538*cf066674SRichard Henderson             *gen_args++ = tmp = *args++;
539*cf066674SRichard Henderson             nb_oargs = tmp >> 16;
540*cf066674SRichard Henderson             nb_iargs = tmp & 0xffff;
541*cf066674SRichard Henderson             nb_args = nb_oargs + nb_iargs + def->nb_cargs;
5421ff8c541SAurelien Jarno         } else {
543*cf066674SRichard Henderson             nb_oargs = def->nb_oargs;
544*cf066674SRichard Henderson             nb_iargs = def->nb_iargs;
545*cf066674SRichard Henderson             nb_args = def->nb_args;
546*cf066674SRichard Henderson         }
547*cf066674SRichard Henderson 
548*cf066674SRichard Henderson         /* Do copy propagation */
549*cf066674SRichard Henderson         for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
55022613af4SKirill Batuzov             if (temps[args[i]].state == TCG_TEMP_COPY) {
551e590d4e6SAurelien Jarno                 args[i] = find_better_copy(s, args[i]);
55222613af4SKirill Batuzov             }
55322613af4SKirill Batuzov         }
55422613af4SKirill Batuzov 
55553108fb5SKirill Batuzov         /* For commutative operations make constant second argument */
55653108fb5SKirill Batuzov         switch (op) {
55753108fb5SKirill Batuzov         CASE_OP_32_64(add):
55853108fb5SKirill Batuzov         CASE_OP_32_64(mul):
5599a81090bSKirill Batuzov         CASE_OP_32_64(and):
5609a81090bSKirill Batuzov         CASE_OP_32_64(or):
5619a81090bSKirill Batuzov         CASE_OP_32_64(xor):
562cb25c80aSRichard Henderson         CASE_OP_32_64(eqv):
563cb25c80aSRichard Henderson         CASE_OP_32_64(nand):
564cb25c80aSRichard Henderson         CASE_OP_32_64(nor):
56503271524SRichard Henderson         CASE_OP_32_64(muluh):
56603271524SRichard Henderson         CASE_OP_32_64(mulsh):
56724c9ae4eSRichard Henderson             swap_commutative(args[0], &args[1], &args[2]);
56853108fb5SKirill Batuzov             break;
56965a7cce1SAurelien Jarno         CASE_OP_32_64(brcond):
57024c9ae4eSRichard Henderson             if (swap_commutative(-1, &args[0], &args[1])) {
57165a7cce1SAurelien Jarno                 args[2] = tcg_swap_cond(args[2]);
57265a7cce1SAurelien Jarno             }
57365a7cce1SAurelien Jarno             break;
57465a7cce1SAurelien Jarno         CASE_OP_32_64(setcond):
57524c9ae4eSRichard Henderson             if (swap_commutative(args[0], &args[1], &args[2])) {
57665a7cce1SAurelien Jarno                 args[3] = tcg_swap_cond(args[3]);
57765a7cce1SAurelien Jarno             }
57865a7cce1SAurelien Jarno             break;
579fa01a208SRichard Henderson         CASE_OP_32_64(movcond):
58024c9ae4eSRichard Henderson             if (swap_commutative(-1, &args[1], &args[2])) {
58124c9ae4eSRichard Henderson                 args[5] = tcg_swap_cond(args[5]);
582fa01a208SRichard Henderson             }
5835d8f5363SRichard Henderson             /* For movcond, we canonicalize the "false" input reg to match
5845d8f5363SRichard Henderson                the destination reg so that the tcg backend can implement
5855d8f5363SRichard Henderson                a "move if true" operation.  */
58624c9ae4eSRichard Henderson             if (swap_commutative(args[0], &args[4], &args[3])) {
58724c9ae4eSRichard Henderson                 args[5] = tcg_invert_cond(args[5]);
5885d8f5363SRichard Henderson             }
5891e484e61SRichard Henderson             break;
590d7156f7cSRichard Henderson         CASE_OP_32_64(add2):
5911e484e61SRichard Henderson             swap_commutative(args[0], &args[2], &args[4]);
5921e484e61SRichard Henderson             swap_commutative(args[1], &args[3], &args[5]);
5931e484e61SRichard Henderson             break;
594d7156f7cSRichard Henderson         CASE_OP_32_64(mulu2):
5954d3203fdSRichard Henderson         CASE_OP_32_64(muls2):
5961414968aSRichard Henderson             swap_commutative(args[0], &args[2], &args[3]);
5971414968aSRichard Henderson             break;
5980bfcb865SRichard Henderson         case INDEX_op_brcond2_i32:
5990bfcb865SRichard Henderson             if (swap_commutative2(&args[0], &args[2])) {
6000bfcb865SRichard Henderson                 args[4] = tcg_swap_cond(args[4]);
6010bfcb865SRichard Henderson             }
6020bfcb865SRichard Henderson             break;
6030bfcb865SRichard Henderson         case INDEX_op_setcond2_i32:
6040bfcb865SRichard Henderson             if (swap_commutative2(&args[1], &args[3])) {
6050bfcb865SRichard Henderson                 args[5] = tcg_swap_cond(args[5]);
6060bfcb865SRichard Henderson             }
6070bfcb865SRichard Henderson             break;
60853108fb5SKirill Batuzov         default:
60953108fb5SKirill Batuzov             break;
61053108fb5SKirill Batuzov         }
61153108fb5SKirill Batuzov 
6122d497542SRichard Henderson         /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
6132d497542SRichard Henderson            and "sub r, 0, a => neg r, a" case.  */
61401ee5282SAurelien Jarno         switch (op) {
61501ee5282SAurelien Jarno         CASE_OP_32_64(shl):
61601ee5282SAurelien Jarno         CASE_OP_32_64(shr):
61701ee5282SAurelien Jarno         CASE_OP_32_64(sar):
61801ee5282SAurelien Jarno         CASE_OP_32_64(rotl):
61901ee5282SAurelien Jarno         CASE_OP_32_64(rotr):
62001ee5282SAurelien Jarno             if (temps[args[1]].state == TCG_TEMP_CONST
62101ee5282SAurelien Jarno                 && temps[args[1]].val == 0) {
62292414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
623e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], 0);
62401ee5282SAurelien Jarno                 args += 3;
62501ee5282SAurelien Jarno                 gen_args += 2;
62601ee5282SAurelien Jarno                 continue;
62701ee5282SAurelien Jarno             }
62801ee5282SAurelien Jarno             break;
6292d497542SRichard Henderson         CASE_OP_32_64(sub):
6302d497542SRichard Henderson             {
6312d497542SRichard Henderson                 TCGOpcode neg_op;
6322d497542SRichard Henderson                 bool have_neg;
6332d497542SRichard Henderson 
6342d497542SRichard Henderson                 if (temps[args[2]].state == TCG_TEMP_CONST) {
6352d497542SRichard Henderson                     /* Proceed with possible constant folding. */
6362d497542SRichard Henderson                     break;
6372d497542SRichard Henderson                 }
6382d497542SRichard Henderson                 if (op == INDEX_op_sub_i32) {
6392d497542SRichard Henderson                     neg_op = INDEX_op_neg_i32;
6402d497542SRichard Henderson                     have_neg = TCG_TARGET_HAS_neg_i32;
6412d497542SRichard Henderson                 } else {
6422d497542SRichard Henderson                     neg_op = INDEX_op_neg_i64;
6432d497542SRichard Henderson                     have_neg = TCG_TARGET_HAS_neg_i64;
6442d497542SRichard Henderson                 }
6452d497542SRichard Henderson                 if (!have_neg) {
6462d497542SRichard Henderson                     break;
6472d497542SRichard Henderson                 }
6482d497542SRichard Henderson                 if (temps[args[1]].state == TCG_TEMP_CONST
6492d497542SRichard Henderson                     && temps[args[1]].val == 0) {
6502d497542SRichard Henderson                     s->gen_opc_buf[op_index] = neg_op;
6512d497542SRichard Henderson                     reset_temp(args[0]);
6522d497542SRichard Henderson                     gen_args[0] = args[0];
6532d497542SRichard Henderson                     gen_args[1] = args[2];
6542d497542SRichard Henderson                     args += 3;
6552d497542SRichard Henderson                     gen_args += 2;
6562d497542SRichard Henderson                     continue;
6572d497542SRichard Henderson                 }
6582d497542SRichard Henderson             }
6592d497542SRichard Henderson             break;
660e201b564SRichard Henderson         CASE_OP_32_64(xor):
661e201b564SRichard Henderson         CASE_OP_32_64(nand):
662e201b564SRichard Henderson             if (temps[args[1]].state != TCG_TEMP_CONST
663e201b564SRichard Henderson                 && temps[args[2]].state == TCG_TEMP_CONST
664e201b564SRichard Henderson                 && temps[args[2]].val == -1) {
665e201b564SRichard Henderson                 i = 1;
666e201b564SRichard Henderson                 goto try_not;
667e201b564SRichard Henderson             }
668e201b564SRichard Henderson             break;
669e201b564SRichard Henderson         CASE_OP_32_64(nor):
670e201b564SRichard Henderson             if (temps[args[1]].state != TCG_TEMP_CONST
671e201b564SRichard Henderson                 && temps[args[2]].state == TCG_TEMP_CONST
672e201b564SRichard Henderson                 && temps[args[2]].val == 0) {
673e201b564SRichard Henderson                 i = 1;
674e201b564SRichard Henderson                 goto try_not;
675e201b564SRichard Henderson             }
676e201b564SRichard Henderson             break;
677e201b564SRichard Henderson         CASE_OP_32_64(andc):
678e201b564SRichard Henderson             if (temps[args[2]].state != TCG_TEMP_CONST
679e201b564SRichard Henderson                 && temps[args[1]].state == TCG_TEMP_CONST
680e201b564SRichard Henderson                 && temps[args[1]].val == -1) {
681e201b564SRichard Henderson                 i = 2;
682e201b564SRichard Henderson                 goto try_not;
683e201b564SRichard Henderson             }
684e201b564SRichard Henderson             break;
685e201b564SRichard Henderson         CASE_OP_32_64(orc):
686e201b564SRichard Henderson         CASE_OP_32_64(eqv):
687e201b564SRichard Henderson             if (temps[args[2]].state != TCG_TEMP_CONST
688e201b564SRichard Henderson                 && temps[args[1]].state == TCG_TEMP_CONST
689e201b564SRichard Henderson                 && temps[args[1]].val == 0) {
690e201b564SRichard Henderson                 i = 2;
691e201b564SRichard Henderson                 goto try_not;
692e201b564SRichard Henderson             }
693e201b564SRichard Henderson             break;
694e201b564SRichard Henderson         try_not:
695e201b564SRichard Henderson             {
696e201b564SRichard Henderson                 TCGOpcode not_op;
697e201b564SRichard Henderson                 bool have_not;
698e201b564SRichard Henderson 
699e201b564SRichard Henderson                 if (def->flags & TCG_OPF_64BIT) {
700e201b564SRichard Henderson                     not_op = INDEX_op_not_i64;
701e201b564SRichard Henderson                     have_not = TCG_TARGET_HAS_not_i64;
702e201b564SRichard Henderson                 } else {
703e201b564SRichard Henderson                     not_op = INDEX_op_not_i32;
704e201b564SRichard Henderson                     have_not = TCG_TARGET_HAS_not_i32;
705e201b564SRichard Henderson                 }
706e201b564SRichard Henderson                 if (!have_not) {
707e201b564SRichard Henderson                     break;
708e201b564SRichard Henderson                 }
709e201b564SRichard Henderson                 s->gen_opc_buf[op_index] = not_op;
710e201b564SRichard Henderson                 reset_temp(args[0]);
711e201b564SRichard Henderson                 gen_args[0] = args[0];
712e201b564SRichard Henderson                 gen_args[1] = args[i];
713e201b564SRichard Henderson                 args += 3;
714e201b564SRichard Henderson                 gen_args += 2;
715e201b564SRichard Henderson                 continue;
716e201b564SRichard Henderson             }
71701ee5282SAurelien Jarno         default:
71801ee5282SAurelien Jarno             break;
71901ee5282SAurelien Jarno         }
72001ee5282SAurelien Jarno 
721464a1441SRichard Henderson         /* Simplify expression for "op r, a, const => mov r, a" cases */
72253108fb5SKirill Batuzov         switch (op) {
72353108fb5SKirill Batuzov         CASE_OP_32_64(add):
72453108fb5SKirill Batuzov         CASE_OP_32_64(sub):
72555c0975cSKirill Batuzov         CASE_OP_32_64(shl):
72655c0975cSKirill Batuzov         CASE_OP_32_64(shr):
72755c0975cSKirill Batuzov         CASE_OP_32_64(sar):
72825c4d9ccSRichard Henderson         CASE_OP_32_64(rotl):
72925c4d9ccSRichard Henderson         CASE_OP_32_64(rotr):
73038ee188bSAurelien Jarno         CASE_OP_32_64(or):
73138ee188bSAurelien Jarno         CASE_OP_32_64(xor):
732464a1441SRichard Henderson         CASE_OP_32_64(andc):
733464a1441SRichard Henderson             if (temps[args[1]].state != TCG_TEMP_CONST
734464a1441SRichard Henderson                 && temps[args[2]].state == TCG_TEMP_CONST
73553108fb5SKirill Batuzov                 && temps[args[2]].val == 0) {
736464a1441SRichard Henderson                 goto do_mov3;
737464a1441SRichard Henderson             }
738464a1441SRichard Henderson             break;
739464a1441SRichard Henderson         CASE_OP_32_64(and):
740464a1441SRichard Henderson         CASE_OP_32_64(orc):
741464a1441SRichard Henderson         CASE_OP_32_64(eqv):
742464a1441SRichard Henderson             if (temps[args[1]].state != TCG_TEMP_CONST
743464a1441SRichard Henderson                 && temps[args[2]].state == TCG_TEMP_CONST
744464a1441SRichard Henderson                 && temps[args[2]].val == -1) {
745464a1441SRichard Henderson                 goto do_mov3;
746464a1441SRichard Henderson             }
747464a1441SRichard Henderson             break;
748464a1441SRichard Henderson         do_mov3:
749e590d4e6SAurelien Jarno             if (temps_are_copies(args[0], args[1])) {
75092414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_nop;
75153108fb5SKirill Batuzov             } else {
75292414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_mov(op);
753b80bb016SAurelien Jarno                 tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
75453108fb5SKirill Batuzov                 gen_args += 2;
75553108fb5SKirill Batuzov             }
756fedc0da2SAurelien Jarno             args += 3;
75753108fb5SKirill Batuzov             continue;
75856e49438SAurelien Jarno         default:
75956e49438SAurelien Jarno             break;
76056e49438SAurelien Jarno         }
76156e49438SAurelien Jarno 
7623031244bSAurelien Jarno         /* Simplify using known-zero bits. Currently only ops with a single
7633031244bSAurelien Jarno            output argument is supported. */
7643a9d8b17SPaolo Bonzini         mask = -1;
765633f6502SPaolo Bonzini         affected = -1;
7663a9d8b17SPaolo Bonzini         switch (op) {
7673a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext8s):
7683a9d8b17SPaolo Bonzini             if ((temps[args[1]].mask & 0x80) != 0) {
7693a9d8b17SPaolo Bonzini                 break;
7703a9d8b17SPaolo Bonzini             }
7713a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext8u):
7723a9d8b17SPaolo Bonzini             mask = 0xff;
7733a9d8b17SPaolo Bonzini             goto and_const;
7743a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext16s):
7753a9d8b17SPaolo Bonzini             if ((temps[args[1]].mask & 0x8000) != 0) {
7763a9d8b17SPaolo Bonzini                 break;
7773a9d8b17SPaolo Bonzini             }
7783a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext16u):
7793a9d8b17SPaolo Bonzini             mask = 0xffff;
7803a9d8b17SPaolo Bonzini             goto and_const;
7813a9d8b17SPaolo Bonzini         case INDEX_op_ext32s_i64:
7823a9d8b17SPaolo Bonzini             if ((temps[args[1]].mask & 0x80000000) != 0) {
7833a9d8b17SPaolo Bonzini                 break;
7843a9d8b17SPaolo Bonzini             }
7853a9d8b17SPaolo Bonzini         case INDEX_op_ext32u_i64:
7863a9d8b17SPaolo Bonzini             mask = 0xffffffffU;
7873a9d8b17SPaolo Bonzini             goto and_const;
7883a9d8b17SPaolo Bonzini 
7893a9d8b17SPaolo Bonzini         CASE_OP_32_64(and):
7903a9d8b17SPaolo Bonzini             mask = temps[args[2]].mask;
7913a9d8b17SPaolo Bonzini             if (temps[args[2]].state == TCG_TEMP_CONST) {
7923a9d8b17SPaolo Bonzini         and_const:
793633f6502SPaolo Bonzini                 affected = temps[args[1]].mask & ~mask;
7943a9d8b17SPaolo Bonzini             }
7953a9d8b17SPaolo Bonzini             mask = temps[args[1]].mask & mask;
7963a9d8b17SPaolo Bonzini             break;
7973a9d8b17SPaolo Bonzini 
79823ec69edSRichard Henderson         CASE_OP_32_64(andc):
79923ec69edSRichard Henderson             /* Known-zeros does not imply known-ones.  Therefore unless
80023ec69edSRichard Henderson                args[2] is constant, we can't infer anything from it.  */
80123ec69edSRichard Henderson             if (temps[args[2]].state == TCG_TEMP_CONST) {
80223ec69edSRichard Henderson                 mask = ~temps[args[2]].mask;
80323ec69edSRichard Henderson                 goto and_const;
80423ec69edSRichard Henderson             }
80523ec69edSRichard Henderson             /* But we certainly know nothing outside args[1] may be set. */
80623ec69edSRichard Henderson             mask = temps[args[1]].mask;
80723ec69edSRichard Henderson             break;
80823ec69edSRichard Henderson 
809e46b225aSAurelien Jarno         case INDEX_op_sar_i32:
8103a9d8b17SPaolo Bonzini             if (temps[args[2]].state == TCG_TEMP_CONST) {
81150c5c4d1SRichard Henderson                 tmp = temps[args[2]].val & 31;
81250c5c4d1SRichard Henderson                 mask = (int32_t)temps[args[1]].mask >> tmp;
813e46b225aSAurelien Jarno             }
814e46b225aSAurelien Jarno             break;
815e46b225aSAurelien Jarno         case INDEX_op_sar_i64:
816e46b225aSAurelien Jarno             if (temps[args[2]].state == TCG_TEMP_CONST) {
81750c5c4d1SRichard Henderson                 tmp = temps[args[2]].val & 63;
81850c5c4d1SRichard Henderson                 mask = (int64_t)temps[args[1]].mask >> tmp;
8193a9d8b17SPaolo Bonzini             }
8203a9d8b17SPaolo Bonzini             break;
8213a9d8b17SPaolo Bonzini 
822e46b225aSAurelien Jarno         case INDEX_op_shr_i32:
8233a9d8b17SPaolo Bonzini             if (temps[args[2]].state == TCG_TEMP_CONST) {
82450c5c4d1SRichard Henderson                 tmp = temps[args[2]].val & 31;
82550c5c4d1SRichard Henderson                 mask = (uint32_t)temps[args[1]].mask >> tmp;
826e46b225aSAurelien Jarno             }
827e46b225aSAurelien Jarno             break;
828e46b225aSAurelien Jarno         case INDEX_op_shr_i64:
829e46b225aSAurelien Jarno             if (temps[args[2]].state == TCG_TEMP_CONST) {
83050c5c4d1SRichard Henderson                 tmp = temps[args[2]].val & 63;
83150c5c4d1SRichard Henderson                 mask = (uint64_t)temps[args[1]].mask >> tmp;
8323a9d8b17SPaolo Bonzini             }
8333a9d8b17SPaolo Bonzini             break;
8343a9d8b17SPaolo Bonzini 
8354bb7a41eSRichard Henderson         case INDEX_op_trunc_shr_i32:
8364bb7a41eSRichard Henderson             mask = (uint64_t)temps[args[1]].mask >> args[2];
8374bb7a41eSRichard Henderson             break;
8384bb7a41eSRichard Henderson 
8393a9d8b17SPaolo Bonzini         CASE_OP_32_64(shl):
8403a9d8b17SPaolo Bonzini             if (temps[args[2]].state == TCG_TEMP_CONST) {
84150c5c4d1SRichard Henderson                 tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
84250c5c4d1SRichard Henderson                 mask = temps[args[1]].mask << tmp;
8433a9d8b17SPaolo Bonzini             }
8443a9d8b17SPaolo Bonzini             break;
8453a9d8b17SPaolo Bonzini 
8463a9d8b17SPaolo Bonzini         CASE_OP_32_64(neg):
8473a9d8b17SPaolo Bonzini             /* Set to 1 all bits to the left of the rightmost.  */
8483a9d8b17SPaolo Bonzini             mask = -(temps[args[1]].mask & -temps[args[1]].mask);
8493a9d8b17SPaolo Bonzini             break;
8503a9d8b17SPaolo Bonzini 
8513a9d8b17SPaolo Bonzini         CASE_OP_32_64(deposit):
852d998e555SRichard Henderson             mask = deposit64(temps[args[1]].mask, args[3], args[4],
853d998e555SRichard Henderson                              temps[args[2]].mask);
8543a9d8b17SPaolo Bonzini             break;
8553a9d8b17SPaolo Bonzini 
8563a9d8b17SPaolo Bonzini         CASE_OP_32_64(or):
8573a9d8b17SPaolo Bonzini         CASE_OP_32_64(xor):
8583a9d8b17SPaolo Bonzini             mask = temps[args[1]].mask | temps[args[2]].mask;
8593a9d8b17SPaolo Bonzini             break;
8603a9d8b17SPaolo Bonzini 
8613a9d8b17SPaolo Bonzini         CASE_OP_32_64(setcond):
8623a9d8b17SPaolo Bonzini             mask = 1;
8633a9d8b17SPaolo Bonzini             break;
8643a9d8b17SPaolo Bonzini 
8653a9d8b17SPaolo Bonzini         CASE_OP_32_64(movcond):
8663a9d8b17SPaolo Bonzini             mask = temps[args[3]].mask | temps[args[4]].mask;
8673a9d8b17SPaolo Bonzini             break;
8683a9d8b17SPaolo Bonzini 
869c8d70272SAurelien Jarno         CASE_OP_32_64(ld8u):
870c8d70272SAurelien Jarno         case INDEX_op_qemu_ld8u:
871c8d70272SAurelien Jarno             mask = 0xff;
872c8d70272SAurelien Jarno             break;
873c8d70272SAurelien Jarno         CASE_OP_32_64(ld16u):
874c8d70272SAurelien Jarno         case INDEX_op_qemu_ld16u:
875c8d70272SAurelien Jarno             mask = 0xffff;
876c8d70272SAurelien Jarno             break;
877c8d70272SAurelien Jarno         case INDEX_op_ld32u_i64:
878c8d70272SAurelien Jarno #if TCG_TARGET_REG_BITS == 64
879c8d70272SAurelien Jarno         case INDEX_op_qemu_ld32u:
880c8d70272SAurelien Jarno #endif
881c8d70272SAurelien Jarno             mask = 0xffffffffu;
882c8d70272SAurelien Jarno             break;
883c8d70272SAurelien Jarno 
884c8d70272SAurelien Jarno         CASE_OP_32_64(qemu_ld):
885c8d70272SAurelien Jarno             {
886*cf066674SRichard Henderson                 TCGMemOp mop = args[nb_oargs + nb_iargs];
887c8d70272SAurelien Jarno                 if (!(mop & MO_SIGN)) {
888c8d70272SAurelien Jarno                     mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
889c8d70272SAurelien Jarno                 }
890c8d70272SAurelien Jarno             }
891c8d70272SAurelien Jarno             break;
892c8d70272SAurelien Jarno 
8933a9d8b17SPaolo Bonzini         default:
8943a9d8b17SPaolo Bonzini             break;
8953a9d8b17SPaolo Bonzini         }
8963a9d8b17SPaolo Bonzini 
897f096dc96SAurelien Jarno         /* 32-bit ops (non 64-bit ops and non load/store ops) generate 32-bit
898f096dc96SAurelien Jarno            results */
899c8d70272SAurelien Jarno         if (!(def->flags & (TCG_OPF_CALL_CLOBBER | TCG_OPF_64BIT))) {
900f096dc96SAurelien Jarno             mask &= 0xffffffffu;
901f096dc96SAurelien Jarno         }
902f096dc96SAurelien Jarno 
903633f6502SPaolo Bonzini         if (mask == 0) {
904*cf066674SRichard Henderson             assert(nb_oargs == 1);
905633f6502SPaolo Bonzini             s->gen_opc_buf[op_index] = op_to_movi(op);
906633f6502SPaolo Bonzini             tcg_opt_gen_movi(gen_args, args[0], 0);
907*cf066674SRichard Henderson             args += nb_args;
908633f6502SPaolo Bonzini             gen_args += 2;
909633f6502SPaolo Bonzini             continue;
910633f6502SPaolo Bonzini         }
911633f6502SPaolo Bonzini         if (affected == 0) {
912*cf066674SRichard Henderson             assert(nb_oargs == 1);
913633f6502SPaolo Bonzini             if (temps_are_copies(args[0], args[1])) {
914633f6502SPaolo Bonzini                 s->gen_opc_buf[op_index] = INDEX_op_nop;
915633f6502SPaolo Bonzini             } else if (temps[args[1]].state != TCG_TEMP_CONST) {
916633f6502SPaolo Bonzini                 s->gen_opc_buf[op_index] = op_to_mov(op);
917633f6502SPaolo Bonzini                 tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
918633f6502SPaolo Bonzini                 gen_args += 2;
919633f6502SPaolo Bonzini             } else {
920633f6502SPaolo Bonzini                 s->gen_opc_buf[op_index] = op_to_movi(op);
921633f6502SPaolo Bonzini                 tcg_opt_gen_movi(gen_args, args[0], temps[args[1]].val);
922633f6502SPaolo Bonzini                 gen_args += 2;
923633f6502SPaolo Bonzini             }
924*cf066674SRichard Henderson             args += nb_args;
925633f6502SPaolo Bonzini             continue;
926633f6502SPaolo Bonzini         }
927633f6502SPaolo Bonzini 
92856e49438SAurelien Jarno         /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
92956e49438SAurelien Jarno         switch (op) {
93061251c0cSAurelien Jarno         CASE_OP_32_64(and):
93153108fb5SKirill Batuzov         CASE_OP_32_64(mul):
93203271524SRichard Henderson         CASE_OP_32_64(muluh):
93303271524SRichard Henderson         CASE_OP_32_64(mulsh):
93453108fb5SKirill Batuzov             if ((temps[args[2]].state == TCG_TEMP_CONST
93553108fb5SKirill Batuzov                 && temps[args[2]].val == 0)) {
93692414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
937e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], 0);
93853108fb5SKirill Batuzov                 args += 3;
93953108fb5SKirill Batuzov                 gen_args += 2;
94053108fb5SKirill Batuzov                 continue;
94153108fb5SKirill Batuzov             }
94253108fb5SKirill Batuzov             break;
94356e49438SAurelien Jarno         default:
94456e49438SAurelien Jarno             break;
94556e49438SAurelien Jarno         }
94656e49438SAurelien Jarno 
94756e49438SAurelien Jarno         /* Simplify expression for "op r, a, a => mov r, a" cases */
94856e49438SAurelien Jarno         switch (op) {
9499a81090bSKirill Batuzov         CASE_OP_32_64(or):
9509a81090bSKirill Batuzov         CASE_OP_32_64(and):
9510aba1c73SAurelien Jarno             if (temps_are_copies(args[1], args[2])) {
952e590d4e6SAurelien Jarno                 if (temps_are_copies(args[0], args[1])) {
95392414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = INDEX_op_nop;
9549a81090bSKirill Batuzov                 } else {
95592414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = op_to_mov(op);
956b80bb016SAurelien Jarno                     tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
9579a81090bSKirill Batuzov                     gen_args += 2;
9589a81090bSKirill Batuzov                 }
959fedc0da2SAurelien Jarno                 args += 3;
9609a81090bSKirill Batuzov                 continue;
9619a81090bSKirill Batuzov             }
9629a81090bSKirill Batuzov             break;
963fe0de7aaSBlue Swirl         default:
964fe0de7aaSBlue Swirl             break;
96553108fb5SKirill Batuzov         }
96653108fb5SKirill Batuzov 
9673c94193eSAurelien Jarno         /* Simplify expression for "op r, a, a => movi r, 0" cases */
9683c94193eSAurelien Jarno         switch (op) {
969e64e958eSRichard Henderson         CASE_OP_32_64(andc):
9703c94193eSAurelien Jarno         CASE_OP_32_64(sub):
9713c94193eSAurelien Jarno         CASE_OP_32_64(xor):
9723c94193eSAurelien Jarno             if (temps_are_copies(args[1], args[2])) {
97392414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
9743c94193eSAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], 0);
9753c94193eSAurelien Jarno                 gen_args += 2;
9763c94193eSAurelien Jarno                 args += 3;
9773c94193eSAurelien Jarno                 continue;
9783c94193eSAurelien Jarno             }
9793c94193eSAurelien Jarno             break;
9803c94193eSAurelien Jarno         default:
9813c94193eSAurelien Jarno             break;
9823c94193eSAurelien Jarno         }
9833c94193eSAurelien Jarno 
98422613af4SKirill Batuzov         /* Propagate constants through copy operations and do constant
98522613af4SKirill Batuzov            folding.  Constants will be substituted to arguments by register
98622613af4SKirill Batuzov            allocator where needed and possible.  Also detect copies. */
9878f2e8c07SKirill Batuzov         switch (op) {
98822613af4SKirill Batuzov         CASE_OP_32_64(mov):
989e590d4e6SAurelien Jarno             if (temps_are_copies(args[0], args[1])) {
99022613af4SKirill Batuzov                 args += 2;
99192414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_nop;
99222613af4SKirill Batuzov                 break;
99322613af4SKirill Batuzov             }
99422613af4SKirill Batuzov             if (temps[args[1]].state != TCG_TEMP_CONST) {
995b80bb016SAurelien Jarno                 tcg_opt_gen_mov(s, gen_args, args[0], args[1]);
99622613af4SKirill Batuzov                 gen_args += 2;
99722613af4SKirill Batuzov                 args += 2;
99822613af4SKirill Batuzov                 break;
99922613af4SKirill Batuzov             }
100022613af4SKirill Batuzov             /* Source argument is constant.  Rewrite the operation and
100122613af4SKirill Batuzov                let movi case handle it. */
100222613af4SKirill Batuzov             op = op_to_movi(op);
100392414b31SEvgeny Voevodin             s->gen_opc_buf[op_index] = op;
100422613af4SKirill Batuzov             args[1] = temps[args[1]].val;
100522613af4SKirill Batuzov             /* fallthrough */
100622613af4SKirill Batuzov         CASE_OP_32_64(movi):
1007e590d4e6SAurelien Jarno             tcg_opt_gen_movi(gen_args, args[0], args[1]);
100822613af4SKirill Batuzov             gen_args += 2;
100922613af4SKirill Batuzov             args += 2;
101022613af4SKirill Batuzov             break;
10116e14e91bSRichard Henderson 
1012a640f031SKirill Batuzov         CASE_OP_32_64(not):
1013cb25c80aSRichard Henderson         CASE_OP_32_64(neg):
101425c4d9ccSRichard Henderson         CASE_OP_32_64(ext8s):
101525c4d9ccSRichard Henderson         CASE_OP_32_64(ext8u):
101625c4d9ccSRichard Henderson         CASE_OP_32_64(ext16s):
101725c4d9ccSRichard Henderson         CASE_OP_32_64(ext16u):
1018a640f031SKirill Batuzov         case INDEX_op_ext32s_i64:
1019a640f031SKirill Batuzov         case INDEX_op_ext32u_i64:
1020a640f031SKirill Batuzov             if (temps[args[1]].state == TCG_TEMP_CONST) {
102192414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
1022a640f031SKirill Batuzov                 tmp = do_constant_folding(op, temps[args[1]].val, 0);
1023e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
1024a640f031SKirill Batuzov                 gen_args += 2;
1025a640f031SKirill Batuzov                 args += 2;
1026a640f031SKirill Batuzov                 break;
10276e14e91bSRichard Henderson             }
10286e14e91bSRichard Henderson             goto do_default;
10296e14e91bSRichard Henderson 
10304bb7a41eSRichard Henderson         case INDEX_op_trunc_shr_i32:
10314bb7a41eSRichard Henderson             if (temps[args[1]].state == TCG_TEMP_CONST) {
10324bb7a41eSRichard Henderson                 s->gen_opc_buf[op_index] = op_to_movi(op);
10334bb7a41eSRichard Henderson                 tmp = do_constant_folding(op, temps[args[1]].val, args[2]);
10344bb7a41eSRichard Henderson                 tcg_opt_gen_movi(gen_args, args[0], tmp);
10354bb7a41eSRichard Henderson                 gen_args += 2;
10364bb7a41eSRichard Henderson                 args += 3;
10374bb7a41eSRichard Henderson                 break;
10384bb7a41eSRichard Henderson             }
10394bb7a41eSRichard Henderson             goto do_default;
10404bb7a41eSRichard Henderson 
104153108fb5SKirill Batuzov         CASE_OP_32_64(add):
104253108fb5SKirill Batuzov         CASE_OP_32_64(sub):
104353108fb5SKirill Batuzov         CASE_OP_32_64(mul):
10449a81090bSKirill Batuzov         CASE_OP_32_64(or):
10459a81090bSKirill Batuzov         CASE_OP_32_64(and):
10469a81090bSKirill Batuzov         CASE_OP_32_64(xor):
104755c0975cSKirill Batuzov         CASE_OP_32_64(shl):
104855c0975cSKirill Batuzov         CASE_OP_32_64(shr):
104955c0975cSKirill Batuzov         CASE_OP_32_64(sar):
105025c4d9ccSRichard Henderson         CASE_OP_32_64(rotl):
105125c4d9ccSRichard Henderson         CASE_OP_32_64(rotr):
1052cb25c80aSRichard Henderson         CASE_OP_32_64(andc):
1053cb25c80aSRichard Henderson         CASE_OP_32_64(orc):
1054cb25c80aSRichard Henderson         CASE_OP_32_64(eqv):
1055cb25c80aSRichard Henderson         CASE_OP_32_64(nand):
1056cb25c80aSRichard Henderson         CASE_OP_32_64(nor):
105703271524SRichard Henderson         CASE_OP_32_64(muluh):
105803271524SRichard Henderson         CASE_OP_32_64(mulsh):
105901547f7fSRichard Henderson         CASE_OP_32_64(div):
106001547f7fSRichard Henderson         CASE_OP_32_64(divu):
106101547f7fSRichard Henderson         CASE_OP_32_64(rem):
106201547f7fSRichard Henderson         CASE_OP_32_64(remu):
106353108fb5SKirill Batuzov             if (temps[args[1]].state == TCG_TEMP_CONST
106453108fb5SKirill Batuzov                 && temps[args[2]].state == TCG_TEMP_CONST) {
106592414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
106653108fb5SKirill Batuzov                 tmp = do_constant_folding(op, temps[args[1]].val,
106753108fb5SKirill Batuzov                                           temps[args[2]].val);
1068e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
106953108fb5SKirill Batuzov                 gen_args += 2;
107053108fb5SKirill Batuzov                 args += 3;
107153108fb5SKirill Batuzov                 break;
10726e14e91bSRichard Henderson             }
10736e14e91bSRichard Henderson             goto do_default;
10746e14e91bSRichard Henderson 
10757ef55fc9SAurelien Jarno         CASE_OP_32_64(deposit):
10767ef55fc9SAurelien Jarno             if (temps[args[1]].state == TCG_TEMP_CONST
10777ef55fc9SAurelien Jarno                 && temps[args[2]].state == TCG_TEMP_CONST) {
107892414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
1079d998e555SRichard Henderson                 tmp = deposit64(temps[args[1]].val, args[3], args[4],
1080d998e555SRichard Henderson                                 temps[args[2]].val);
10817ef55fc9SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
10827ef55fc9SAurelien Jarno                 gen_args += 2;
10837ef55fc9SAurelien Jarno                 args += 5;
10847ef55fc9SAurelien Jarno                 break;
10856e14e91bSRichard Henderson             }
10866e14e91bSRichard Henderson             goto do_default;
10876e14e91bSRichard Henderson 
1088f8dd19e5SAurelien Jarno         CASE_OP_32_64(setcond):
1089b336ceb6SAurelien Jarno             tmp = do_constant_folding_cond(op, args[1], args[2], args[3]);
1090b336ceb6SAurelien Jarno             if (tmp != 2) {
109192414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = op_to_movi(op);
1092e590d4e6SAurelien Jarno                 tcg_opt_gen_movi(gen_args, args[0], tmp);
1093f8dd19e5SAurelien Jarno                 gen_args += 2;
1094f8dd19e5SAurelien Jarno                 args += 4;
1095f8dd19e5SAurelien Jarno                 break;
10966e14e91bSRichard Henderson             }
10976e14e91bSRichard Henderson             goto do_default;
10986e14e91bSRichard Henderson 
1099fbeaa26cSAurelien Jarno         CASE_OP_32_64(brcond):
1100b336ceb6SAurelien Jarno             tmp = do_constant_folding_cond(op, args[0], args[1], args[2]);
1101b336ceb6SAurelien Jarno             if (tmp != 2) {
1102b336ceb6SAurelien Jarno                 if (tmp) {
1103d193a14aSPaolo Bonzini                     reset_all_temps(nb_temps);
110492414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = INDEX_op_br;
1105fbeaa26cSAurelien Jarno                     gen_args[0] = args[3];
1106fbeaa26cSAurelien Jarno                     gen_args += 1;
1107fbeaa26cSAurelien Jarno                 } else {
110892414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = INDEX_op_nop;
1109fbeaa26cSAurelien Jarno                 }
1110fbeaa26cSAurelien Jarno                 args += 4;
1111fbeaa26cSAurelien Jarno                 break;
11126e14e91bSRichard Henderson             }
11136e14e91bSRichard Henderson             goto do_default;
11146e14e91bSRichard Henderson 
1115fa01a208SRichard Henderson         CASE_OP_32_64(movcond):
1116b336ceb6SAurelien Jarno             tmp = do_constant_folding_cond(op, args[1], args[2], args[5]);
1117b336ceb6SAurelien Jarno             if (tmp != 2) {
1118e590d4e6SAurelien Jarno                 if (temps_are_copies(args[0], args[4-tmp])) {
111992414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = INDEX_op_nop;
1120fa01a208SRichard Henderson                 } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) {
112192414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = op_to_movi(op);
1122e590d4e6SAurelien Jarno                     tcg_opt_gen_movi(gen_args, args[0], temps[args[4-tmp]].val);
1123fa01a208SRichard Henderson                     gen_args += 2;
1124fa01a208SRichard Henderson                 } else {
112592414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = op_to_mov(op);
1126e590d4e6SAurelien Jarno                     tcg_opt_gen_mov(s, gen_args, args[0], args[4-tmp]);
1127fa01a208SRichard Henderson                     gen_args += 2;
1128fa01a208SRichard Henderson                 }
1129fa01a208SRichard Henderson                 args += 6;
1130fa01a208SRichard Henderson                 break;
11316e14e91bSRichard Henderson             }
11326e14e91bSRichard Henderson             goto do_default;
11336e14e91bSRichard Henderson 
1134212c328dSRichard Henderson         case INDEX_op_add2_i32:
1135212c328dSRichard Henderson         case INDEX_op_sub2_i32:
1136212c328dSRichard Henderson             if (temps[args[2]].state == TCG_TEMP_CONST
1137212c328dSRichard Henderson                 && temps[args[3]].state == TCG_TEMP_CONST
1138212c328dSRichard Henderson                 && temps[args[4]].state == TCG_TEMP_CONST
1139212c328dSRichard Henderson                 && temps[args[5]].state == TCG_TEMP_CONST) {
1140212c328dSRichard Henderson                 uint32_t al = temps[args[2]].val;
1141212c328dSRichard Henderson                 uint32_t ah = temps[args[3]].val;
1142212c328dSRichard Henderson                 uint32_t bl = temps[args[4]].val;
1143212c328dSRichard Henderson                 uint32_t bh = temps[args[5]].val;
1144212c328dSRichard Henderson                 uint64_t a = ((uint64_t)ah << 32) | al;
1145212c328dSRichard Henderson                 uint64_t b = ((uint64_t)bh << 32) | bl;
1146212c328dSRichard Henderson                 TCGArg rl, rh;
1147212c328dSRichard Henderson 
1148212c328dSRichard Henderson                 if (op == INDEX_op_add2_i32) {
1149212c328dSRichard Henderson                     a += b;
1150212c328dSRichard Henderson                 } else {
1151212c328dSRichard Henderson                     a -= b;
1152212c328dSRichard Henderson                 }
1153212c328dSRichard Henderson 
1154212c328dSRichard Henderson                 /* We emit the extra nop when we emit the add2/sub2.  */
115592414b31SEvgeny Voevodin                 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
1156212c328dSRichard Henderson 
1157212c328dSRichard Henderson                 rl = args[0];
1158212c328dSRichard Henderson                 rh = args[1];
115992414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
116092414b31SEvgeny Voevodin                 s->gen_opc_buf[++op_index] = INDEX_op_movi_i32;
1161212c328dSRichard Henderson                 tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)a);
1162212c328dSRichard Henderson                 tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(a >> 32));
1163212c328dSRichard Henderson                 gen_args += 4;
1164212c328dSRichard Henderson                 args += 6;
1165212c328dSRichard Henderson                 break;
1166212c328dSRichard Henderson             }
1167212c328dSRichard Henderson             goto do_default;
1168212c328dSRichard Henderson 
11691414968aSRichard Henderson         case INDEX_op_mulu2_i32:
11701414968aSRichard Henderson             if (temps[args[2]].state == TCG_TEMP_CONST
11711414968aSRichard Henderson                 && temps[args[3]].state == TCG_TEMP_CONST) {
11721414968aSRichard Henderson                 uint32_t a = temps[args[2]].val;
11731414968aSRichard Henderson                 uint32_t b = temps[args[3]].val;
11741414968aSRichard Henderson                 uint64_t r = (uint64_t)a * b;
11751414968aSRichard Henderson                 TCGArg rl, rh;
11761414968aSRichard Henderson 
11771414968aSRichard Henderson                 /* We emit the extra nop when we emit the mulu2.  */
117892414b31SEvgeny Voevodin                 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop);
11791414968aSRichard Henderson 
11801414968aSRichard Henderson                 rl = args[0];
11811414968aSRichard Henderson                 rh = args[1];
118292414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
118392414b31SEvgeny Voevodin                 s->gen_opc_buf[++op_index] = INDEX_op_movi_i32;
11841414968aSRichard Henderson                 tcg_opt_gen_movi(&gen_args[0], rl, (uint32_t)r);
11851414968aSRichard Henderson                 tcg_opt_gen_movi(&gen_args[2], rh, (uint32_t)(r >> 32));
11861414968aSRichard Henderson                 gen_args += 4;
11871414968aSRichard Henderson                 args += 4;
11881414968aSRichard Henderson                 break;
11891414968aSRichard Henderson             }
11901414968aSRichard Henderson             goto do_default;
11911414968aSRichard Henderson 
1192bc1473efSRichard Henderson         case INDEX_op_brcond2_i32:
11936c4382f8SRichard Henderson             tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]);
11946c4382f8SRichard Henderson             if (tmp != 2) {
11956c4382f8SRichard Henderson                 if (tmp) {
1196d193a14aSPaolo Bonzini                     reset_all_temps(nb_temps);
119792414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = INDEX_op_br;
11986c4382f8SRichard Henderson                     gen_args[0] = args[5];
11996c4382f8SRichard Henderson                     gen_args += 1;
12006c4382f8SRichard Henderson                 } else {
120192414b31SEvgeny Voevodin                     s->gen_opc_buf[op_index] = INDEX_op_nop;
12026c4382f8SRichard Henderson                 }
12036c4382f8SRichard Henderson             } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
1204bc1473efSRichard Henderson                        && temps[args[2]].state == TCG_TEMP_CONST
1205bc1473efSRichard Henderson                        && temps[args[3]].state == TCG_TEMP_CONST
1206bc1473efSRichard Henderson                        && temps[args[2]].val == 0
1207bc1473efSRichard Henderson                        && temps[args[3]].val == 0) {
12086c4382f8SRichard Henderson                 /* Simplify LT/GE comparisons vs zero to a single compare
12096c4382f8SRichard Henderson                    vs the high word of the input.  */
1210d193a14aSPaolo Bonzini                 reset_all_temps(nb_temps);
121192414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_brcond_i32;
1212bc1473efSRichard Henderson                 gen_args[0] = args[1];
1213bc1473efSRichard Henderson                 gen_args[1] = args[3];
1214bc1473efSRichard Henderson                 gen_args[2] = args[4];
1215bc1473efSRichard Henderson                 gen_args[3] = args[5];
1216bc1473efSRichard Henderson                 gen_args += 4;
12176c4382f8SRichard Henderson             } else {
1218bc1473efSRichard Henderson                 goto do_default;
12196c4382f8SRichard Henderson             }
12206c4382f8SRichard Henderson             args += 6;
12216c4382f8SRichard Henderson             break;
1222bc1473efSRichard Henderson 
1223bc1473efSRichard Henderson         case INDEX_op_setcond2_i32:
12246c4382f8SRichard Henderson             tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
12256c4382f8SRichard Henderson             if (tmp != 2) {
122692414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_movi_i32;
12276c4382f8SRichard Henderson                 tcg_opt_gen_movi(gen_args, args[0], tmp);
12286c4382f8SRichard Henderson                 gen_args += 2;
12296c4382f8SRichard Henderson             } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
1230bc1473efSRichard Henderson                        && temps[args[3]].state == TCG_TEMP_CONST
1231bc1473efSRichard Henderson                        && temps[args[4]].state == TCG_TEMP_CONST
1232bc1473efSRichard Henderson                        && temps[args[3]].val == 0
1233bc1473efSRichard Henderson                        && temps[args[4]].val == 0) {
12346c4382f8SRichard Henderson                 /* Simplify LT/GE comparisons vs zero to a single compare
12356c4382f8SRichard Henderson                    vs the high word of the input.  */
123692414b31SEvgeny Voevodin                 s->gen_opc_buf[op_index] = INDEX_op_setcond_i32;
123766e61b55SAurelien Jarno                 reset_temp(args[0]);
1238bc1473efSRichard Henderson                 gen_args[0] = args[0];
1239bc1473efSRichard Henderson                 gen_args[1] = args[2];
1240bc1473efSRichard Henderson                 gen_args[2] = args[4];
1241bc1473efSRichard Henderson                 gen_args[3] = args[5];
1242bc1473efSRichard Henderson                 gen_args += 4;
12436c4382f8SRichard Henderson             } else {
12446c4382f8SRichard Henderson                 goto do_default;
12456c4382f8SRichard Henderson             }
1246bc1473efSRichard Henderson             args += 6;
1247bc1473efSRichard Henderson             break;
1248bc1473efSRichard Henderson 
12498f2e8c07SKirill Batuzov         case INDEX_op_call:
1250*cf066674SRichard Henderson             if (!(args[nb_oargs + nb_iargs + 1]
1251*cf066674SRichard Henderson                   & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
125222613af4SKirill Batuzov                 for (i = 0; i < nb_globals; i++) {
1253e590d4e6SAurelien Jarno                     reset_temp(i);
125422613af4SKirill Batuzov                 }
125522613af4SKirill Batuzov             }
1256*cf066674SRichard Henderson             goto do_reset_output;
12576e14e91bSRichard Henderson 
12588f2e8c07SKirill Batuzov         default:
12596e14e91bSRichard Henderson         do_default:
12606e14e91bSRichard Henderson             /* Default case: we know nothing about operation (or were unable
12616e14e91bSRichard Henderson                to compute the operation result) so no propagation is done.
12626e14e91bSRichard Henderson                We trash everything if the operation is the end of a basic
12633a9d8b17SPaolo Bonzini                block, otherwise we only trash the output args.  "mask" is
12643a9d8b17SPaolo Bonzini                the non-zero bits mask for the first output arg.  */
1265a2550660SAurelien Jarno             if (def->flags & TCG_OPF_BB_END) {
1266d193a14aSPaolo Bonzini                 reset_all_temps(nb_temps);
1267a2550660SAurelien Jarno             } else {
1268*cf066674SRichard Henderson         do_reset_output:
1269*cf066674SRichard Henderson                 for (i = 0; i < nb_oargs; i++) {
1270e590d4e6SAurelien Jarno                     reset_temp(args[i]);
12713031244bSAurelien Jarno                     /* Save the corresponding known-zero bits mask for the
12723031244bSAurelien Jarno                        first output argument (only one supported so far). */
12733031244bSAurelien Jarno                     if (i == 0) {
12743031244bSAurelien Jarno                         temps[args[i]].mask = mask;
12753031244bSAurelien Jarno                     }
127622613af4SKirill Batuzov                 }
1277a2550660SAurelien Jarno             }
1278*cf066674SRichard Henderson             for (i = 0; i < nb_args; i++) {
12798f2e8c07SKirill Batuzov                 gen_args[i] = args[i];
12808f2e8c07SKirill Batuzov             }
1281*cf066674SRichard Henderson             args += nb_args;
1282*cf066674SRichard Henderson             gen_args += nb_args;
12838f2e8c07SKirill Batuzov             break;
12848f2e8c07SKirill Batuzov         }
12858f2e8c07SKirill Batuzov     }
12868f2e8c07SKirill Batuzov 
12878f2e8c07SKirill Batuzov     return gen_args;
12888f2e8c07SKirill Batuzov }
12898f2e8c07SKirill Batuzov 
12908f2e8c07SKirill Batuzov TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr,
12918f2e8c07SKirill Batuzov         TCGArg *args, TCGOpDef *tcg_op_defs)
12928f2e8c07SKirill Batuzov {
12938f2e8c07SKirill Batuzov     TCGArg *res;
12948f2e8c07SKirill Batuzov     res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs);
12958f2e8c07SKirill Batuzov     return res;
12968f2e8c07SKirill Batuzov }
1297