xref: /openbmc/qemu/tcg/optimize.c (revision 90163900)
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 
26757e725bSPeter Maydell #include "qemu/osdep.h"
27dcb32f1dSPhilippe Mathieu-Daudé #include "tcg/tcg-op.h"
28*90163900SRichard Henderson #include "tcg-internal.h"
298f2e8c07SKirill Batuzov 
308f2e8c07SKirill Batuzov #define CASE_OP_32_64(x)                        \
318f2e8c07SKirill Batuzov         glue(glue(case INDEX_op_, x), _i32):    \
328f2e8c07SKirill Batuzov         glue(glue(case INDEX_op_, x), _i64)
338f2e8c07SKirill Batuzov 
34170ba88fSRichard Henderson #define CASE_OP_32_64_VEC(x)                    \
35170ba88fSRichard Henderson         glue(glue(case INDEX_op_, x), _i32):    \
36170ba88fSRichard Henderson         glue(glue(case INDEX_op_, x), _i64):    \
37170ba88fSRichard Henderson         glue(glue(case INDEX_op_, x), _vec)
38170ba88fSRichard Henderson 
396fcb98edSRichard Henderson typedef struct TempOptInfo {
40b41059ddSAurelien Jarno     bool is_const;
416349039dSRichard Henderson     TCGTemp *prev_copy;
426349039dSRichard Henderson     TCGTemp *next_copy;
4354795544SRichard Henderson     uint64_t val;
4454795544SRichard Henderson     uint64_t mask;
456fcb98edSRichard Henderson } TempOptInfo;
4622613af4SKirill Batuzov 
476fcb98edSRichard Henderson static inline TempOptInfo *ts_info(TCGTemp *ts)
48d9c769c6SAurelien Jarno {
496349039dSRichard Henderson     return ts->state_ptr;
50d9c769c6SAurelien Jarno }
51d9c769c6SAurelien Jarno 
526fcb98edSRichard Henderson static inline TempOptInfo *arg_info(TCGArg arg)
53d9c769c6SAurelien Jarno {
546349039dSRichard Henderson     return ts_info(arg_temp(arg));
556349039dSRichard Henderson }
566349039dSRichard Henderson 
576349039dSRichard Henderson static inline bool ts_is_const(TCGTemp *ts)
586349039dSRichard Henderson {
596349039dSRichard Henderson     return ts_info(ts)->is_const;
606349039dSRichard Henderson }
616349039dSRichard Henderson 
626349039dSRichard Henderson static inline bool arg_is_const(TCGArg arg)
636349039dSRichard Henderson {
646349039dSRichard Henderson     return ts_is_const(arg_temp(arg));
656349039dSRichard Henderson }
666349039dSRichard Henderson 
676349039dSRichard Henderson static inline bool ts_is_copy(TCGTemp *ts)
686349039dSRichard Henderson {
696349039dSRichard Henderson     return ts_info(ts)->next_copy != ts;
70d9c769c6SAurelien Jarno }
71d9c769c6SAurelien Jarno 
72b41059ddSAurelien Jarno /* Reset TEMP's state, possibly removing the temp for the list of copies.  */
736349039dSRichard Henderson static void reset_ts(TCGTemp *ts)
7422613af4SKirill Batuzov {
756fcb98edSRichard Henderson     TempOptInfo *ti = ts_info(ts);
766fcb98edSRichard Henderson     TempOptInfo *pi = ts_info(ti->prev_copy);
776fcb98edSRichard Henderson     TempOptInfo *ni = ts_info(ti->next_copy);
786349039dSRichard Henderson 
796349039dSRichard Henderson     ni->prev_copy = ti->prev_copy;
806349039dSRichard Henderson     pi->next_copy = ti->next_copy;
816349039dSRichard Henderson     ti->next_copy = ts;
826349039dSRichard Henderson     ti->prev_copy = ts;
836349039dSRichard Henderson     ti->is_const = false;
846349039dSRichard Henderson     ti->mask = -1;
856349039dSRichard Henderson }
866349039dSRichard Henderson 
876349039dSRichard Henderson static void reset_temp(TCGArg arg)
886349039dSRichard Henderson {
896349039dSRichard Henderson     reset_ts(arg_temp(arg));
9022613af4SKirill Batuzov }
9122613af4SKirill Batuzov 
921208d7ddSAurelien Jarno /* Initialize and activate a temporary.  */
938f17a975SRichard Henderson static void init_ts_info(TCGTempSet *temps_used, TCGTemp *ts)
941208d7ddSAurelien Jarno {
956349039dSRichard Henderson     size_t idx = temp_idx(ts);
968f17a975SRichard Henderson     TempOptInfo *ti;
976349039dSRichard Henderson 
988f17a975SRichard Henderson     if (test_bit(idx, temps_used->l)) {
998f17a975SRichard Henderson         return;
1008f17a975SRichard Henderson     }
1018f17a975SRichard Henderson     set_bit(idx, temps_used->l);
1028f17a975SRichard Henderson 
1038f17a975SRichard Henderson     ti = ts->state_ptr;
1048f17a975SRichard Henderson     if (ti == NULL) {
1058f17a975SRichard Henderson         ti = tcg_malloc(sizeof(TempOptInfo));
1066349039dSRichard Henderson         ts->state_ptr = ti;
1078f17a975SRichard Henderson     }
1088f17a975SRichard Henderson 
1096349039dSRichard Henderson     ti->next_copy = ts;
1106349039dSRichard Henderson     ti->prev_copy = ts;
111c0522136SRichard Henderson     if (ts->kind == TEMP_CONST) {
112c0522136SRichard Henderson         ti->is_const = true;
1138f17a975SRichard Henderson         ti->val = ts->val;
1148f17a975SRichard Henderson         ti->mask = ts->val;
115c0522136SRichard Henderson         if (TCG_TARGET_REG_BITS > 32 && ts->type == TCG_TYPE_I32) {
116c0522136SRichard Henderson             /* High bits of a 32-bit quantity are garbage.  */
117c0522136SRichard Henderson             ti->mask |= ~0xffffffffull;
118c0522136SRichard Henderson         }
119c0522136SRichard Henderson     } else {
1206349039dSRichard Henderson         ti->is_const = false;
1216349039dSRichard Henderson         ti->mask = -1;
122c0522136SRichard Henderson     }
1231208d7ddSAurelien Jarno }
1241208d7ddSAurelien Jarno 
1258f17a975SRichard Henderson static void init_arg_info(TCGTempSet *temps_used, TCGArg arg)
1266349039dSRichard Henderson {
1278f17a975SRichard Henderson     init_ts_info(temps_used, arg_temp(arg));
1286349039dSRichard Henderson }
1296349039dSRichard Henderson 
1306349039dSRichard Henderson static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts)
131e590d4e6SAurelien Jarno {
1324c868ce6SRichard Henderson     TCGTemp *i, *g, *l;
133e590d4e6SAurelien Jarno 
1344c868ce6SRichard Henderson     /* If this is already readonly, we can't do better. */
1354c868ce6SRichard Henderson     if (temp_readonly(ts)) {
1366349039dSRichard Henderson         return ts;
137e590d4e6SAurelien Jarno     }
138e590d4e6SAurelien Jarno 
1394c868ce6SRichard Henderson     g = l = NULL;
1406349039dSRichard Henderson     for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) {
1414c868ce6SRichard Henderson         if (temp_readonly(i)) {
142e590d4e6SAurelien Jarno             return i;
1434c868ce6SRichard Henderson         } else if (i->kind > ts->kind) {
1444c868ce6SRichard Henderson             if (i->kind == TEMP_GLOBAL) {
1454c868ce6SRichard Henderson                 g = i;
1464c868ce6SRichard Henderson             } else if (i->kind == TEMP_LOCAL) {
1474c868ce6SRichard Henderson                 l = i;
148e590d4e6SAurelien Jarno             }
149e590d4e6SAurelien Jarno         }
150e590d4e6SAurelien Jarno     }
151e590d4e6SAurelien Jarno 
1524c868ce6SRichard Henderson     /* If we didn't find a better representation, return the same temp. */
1534c868ce6SRichard Henderson     return g ? g : l ? l : ts;
154e590d4e6SAurelien Jarno }
155e590d4e6SAurelien Jarno 
1566349039dSRichard Henderson static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2)
157e590d4e6SAurelien Jarno {
1586349039dSRichard Henderson     TCGTemp *i;
159e590d4e6SAurelien Jarno 
1606349039dSRichard Henderson     if (ts1 == ts2) {
161e590d4e6SAurelien Jarno         return true;
162e590d4e6SAurelien Jarno     }
163e590d4e6SAurelien Jarno 
1646349039dSRichard Henderson     if (!ts_is_copy(ts1) || !ts_is_copy(ts2)) {
165e590d4e6SAurelien Jarno         return false;
166e590d4e6SAurelien Jarno     }
167e590d4e6SAurelien Jarno 
1686349039dSRichard Henderson     for (i = ts_info(ts1)->next_copy; i != ts1; i = ts_info(i)->next_copy) {
1696349039dSRichard Henderson         if (i == ts2) {
170e590d4e6SAurelien Jarno             return true;
171e590d4e6SAurelien Jarno         }
172e590d4e6SAurelien Jarno     }
173e590d4e6SAurelien Jarno 
174e590d4e6SAurelien Jarno     return false;
175e590d4e6SAurelien Jarno }
176e590d4e6SAurelien Jarno 
1776349039dSRichard Henderson static bool args_are_copies(TCGArg arg1, TCGArg arg2)
1786349039dSRichard Henderson {
1796349039dSRichard Henderson     return ts_are_copies(arg_temp(arg1), arg_temp(arg2));
1806349039dSRichard Henderson }
1816349039dSRichard Henderson 
182acd93701SRichard Henderson static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src)
18322613af4SKirill Batuzov {
1846349039dSRichard Henderson     TCGTemp *dst_ts = arg_temp(dst);
1856349039dSRichard Henderson     TCGTemp *src_ts = arg_temp(src);
186170ba88fSRichard Henderson     const TCGOpDef *def;
1876fcb98edSRichard Henderson     TempOptInfo *di;
1886fcb98edSRichard Henderson     TempOptInfo *si;
18954795544SRichard Henderson     uint64_t mask;
1906349039dSRichard Henderson     TCGOpcode new_op;
1916349039dSRichard Henderson 
1926349039dSRichard Henderson     if (ts_are_copies(dst_ts, src_ts)) {
1935365718aSAurelien Jarno         tcg_op_remove(s, op);
1945365718aSAurelien Jarno         return;
1955365718aSAurelien Jarno     }
1965365718aSAurelien Jarno 
1976349039dSRichard Henderson     reset_ts(dst_ts);
1986349039dSRichard Henderson     di = ts_info(dst_ts);
1996349039dSRichard Henderson     si = ts_info(src_ts);
200170ba88fSRichard Henderson     def = &tcg_op_defs[op->opc];
201170ba88fSRichard Henderson     if (def->flags & TCG_OPF_VECTOR) {
202170ba88fSRichard Henderson         new_op = INDEX_op_mov_vec;
203170ba88fSRichard Henderson     } else if (def->flags & TCG_OPF_64BIT) {
204170ba88fSRichard Henderson         new_op = INDEX_op_mov_i64;
205170ba88fSRichard Henderson     } else {
206170ba88fSRichard Henderson         new_op = INDEX_op_mov_i32;
207170ba88fSRichard Henderson     }
208c45cb8bbSRichard Henderson     op->opc = new_op;
209170ba88fSRichard Henderson     /* TCGOP_VECL and TCGOP_VECE remain unchanged.  */
2106349039dSRichard Henderson     op->args[0] = dst;
2116349039dSRichard Henderson     op->args[1] = src;
212a62f6f56SRichard Henderson 
2136349039dSRichard Henderson     mask = si->mask;
21424666bafSRichard Henderson     if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
21524666bafSRichard Henderson         /* High bits of the destination are now garbage.  */
21624666bafSRichard Henderson         mask |= ~0xffffffffull;
21724666bafSRichard Henderson     }
2186349039dSRichard Henderson     di->mask = mask;
21924666bafSRichard Henderson 
2206349039dSRichard Henderson     if (src_ts->type == dst_ts->type) {
2216fcb98edSRichard Henderson         TempOptInfo *ni = ts_info(si->next_copy);
2226349039dSRichard Henderson 
2236349039dSRichard Henderson         di->next_copy = si->next_copy;
2246349039dSRichard Henderson         di->prev_copy = src_ts;
2256349039dSRichard Henderson         ni->prev_copy = dst_ts;
2266349039dSRichard Henderson         si->next_copy = dst_ts;
2276349039dSRichard Henderson         di->is_const = si->is_const;
2286349039dSRichard Henderson         di->val = si->val;
22922613af4SKirill Batuzov     }
23022613af4SKirill Batuzov }
23122613af4SKirill Batuzov 
2328fe35e04SRichard Henderson static void tcg_opt_gen_movi(TCGContext *s, TCGTempSet *temps_used,
2338fe35e04SRichard Henderson                              TCGOp *op, TCGArg dst, uint64_t val)
2348fe35e04SRichard Henderson {
2358fe35e04SRichard Henderson     const TCGOpDef *def = &tcg_op_defs[op->opc];
2368fe35e04SRichard Henderson     TCGType type;
2378fe35e04SRichard Henderson     TCGTemp *tv;
2388fe35e04SRichard Henderson 
2398fe35e04SRichard Henderson     if (def->flags & TCG_OPF_VECTOR) {
2408fe35e04SRichard Henderson         type = TCGOP_VECL(op) + TCG_TYPE_V64;
2418fe35e04SRichard Henderson     } else if (def->flags & TCG_OPF_64BIT) {
2428fe35e04SRichard Henderson         type = TCG_TYPE_I64;
2438fe35e04SRichard Henderson     } else {
2448fe35e04SRichard Henderson         type = TCG_TYPE_I32;
2458fe35e04SRichard Henderson     }
2468fe35e04SRichard Henderson 
2478fe35e04SRichard Henderson     /* Convert movi to mov with constant temp. */
2488fe35e04SRichard Henderson     tv = tcg_constant_internal(type, val);
2498fe35e04SRichard Henderson     init_ts_info(temps_used, tv);
2508fe35e04SRichard Henderson     tcg_opt_gen_mov(s, op, dst, temp_arg(tv));
2518fe35e04SRichard Henderson }
2528fe35e04SRichard Henderson 
25354795544SRichard Henderson static uint64_t do_constant_folding_2(TCGOpcode op, uint64_t x, uint64_t y)
25453108fb5SKirill Batuzov {
25503271524SRichard Henderson     uint64_t l64, h64;
25603271524SRichard Henderson 
25753108fb5SKirill Batuzov     switch (op) {
25853108fb5SKirill Batuzov     CASE_OP_32_64(add):
25953108fb5SKirill Batuzov         return x + y;
26053108fb5SKirill Batuzov 
26153108fb5SKirill Batuzov     CASE_OP_32_64(sub):
26253108fb5SKirill Batuzov         return x - y;
26353108fb5SKirill Batuzov 
26453108fb5SKirill Batuzov     CASE_OP_32_64(mul):
26553108fb5SKirill Batuzov         return x * y;
26653108fb5SKirill Batuzov 
2679a81090bSKirill Batuzov     CASE_OP_32_64(and):
2689a81090bSKirill Batuzov         return x & y;
2699a81090bSKirill Batuzov 
2709a81090bSKirill Batuzov     CASE_OP_32_64(or):
2719a81090bSKirill Batuzov         return x | y;
2729a81090bSKirill Batuzov 
2739a81090bSKirill Batuzov     CASE_OP_32_64(xor):
2749a81090bSKirill Batuzov         return x ^ y;
2759a81090bSKirill Batuzov 
27655c0975cSKirill Batuzov     case INDEX_op_shl_i32:
27750c5c4d1SRichard Henderson         return (uint32_t)x << (y & 31);
27855c0975cSKirill Batuzov 
27955c0975cSKirill Batuzov     case INDEX_op_shl_i64:
28050c5c4d1SRichard Henderson         return (uint64_t)x << (y & 63);
28155c0975cSKirill Batuzov 
28255c0975cSKirill Batuzov     case INDEX_op_shr_i32:
28350c5c4d1SRichard Henderson         return (uint32_t)x >> (y & 31);
28455c0975cSKirill Batuzov 
28555c0975cSKirill Batuzov     case INDEX_op_shr_i64:
28650c5c4d1SRichard Henderson         return (uint64_t)x >> (y & 63);
28755c0975cSKirill Batuzov 
28855c0975cSKirill Batuzov     case INDEX_op_sar_i32:
28950c5c4d1SRichard Henderson         return (int32_t)x >> (y & 31);
29055c0975cSKirill Batuzov 
29155c0975cSKirill Batuzov     case INDEX_op_sar_i64:
29250c5c4d1SRichard Henderson         return (int64_t)x >> (y & 63);
29355c0975cSKirill Batuzov 
29455c0975cSKirill Batuzov     case INDEX_op_rotr_i32:
29550c5c4d1SRichard Henderson         return ror32(x, y & 31);
29655c0975cSKirill Batuzov 
29755c0975cSKirill Batuzov     case INDEX_op_rotr_i64:
29850c5c4d1SRichard Henderson         return ror64(x, y & 63);
29955c0975cSKirill Batuzov 
30055c0975cSKirill Batuzov     case INDEX_op_rotl_i32:
30150c5c4d1SRichard Henderson         return rol32(x, y & 31);
30255c0975cSKirill Batuzov 
30355c0975cSKirill Batuzov     case INDEX_op_rotl_i64:
30450c5c4d1SRichard Henderson         return rol64(x, y & 63);
30555c0975cSKirill Batuzov 
30625c4d9ccSRichard Henderson     CASE_OP_32_64(not):
307a640f031SKirill Batuzov         return ~x;
308a640f031SKirill Batuzov 
309cb25c80aSRichard Henderson     CASE_OP_32_64(neg):
310cb25c80aSRichard Henderson         return -x;
311cb25c80aSRichard Henderson 
312cb25c80aSRichard Henderson     CASE_OP_32_64(andc):
313cb25c80aSRichard Henderson         return x & ~y;
314cb25c80aSRichard Henderson 
315cb25c80aSRichard Henderson     CASE_OP_32_64(orc):
316cb25c80aSRichard Henderson         return x | ~y;
317cb25c80aSRichard Henderson 
318cb25c80aSRichard Henderson     CASE_OP_32_64(eqv):
319cb25c80aSRichard Henderson         return ~(x ^ y);
320cb25c80aSRichard Henderson 
321cb25c80aSRichard Henderson     CASE_OP_32_64(nand):
322cb25c80aSRichard Henderson         return ~(x & y);
323cb25c80aSRichard Henderson 
324cb25c80aSRichard Henderson     CASE_OP_32_64(nor):
325cb25c80aSRichard Henderson         return ~(x | y);
326cb25c80aSRichard Henderson 
3270e28d006SRichard Henderson     case INDEX_op_clz_i32:
3280e28d006SRichard Henderson         return (uint32_t)x ? clz32(x) : y;
3290e28d006SRichard Henderson 
3300e28d006SRichard Henderson     case INDEX_op_clz_i64:
3310e28d006SRichard Henderson         return x ? clz64(x) : y;
3320e28d006SRichard Henderson 
3330e28d006SRichard Henderson     case INDEX_op_ctz_i32:
3340e28d006SRichard Henderson         return (uint32_t)x ? ctz32(x) : y;
3350e28d006SRichard Henderson 
3360e28d006SRichard Henderson     case INDEX_op_ctz_i64:
3370e28d006SRichard Henderson         return x ? ctz64(x) : y;
3380e28d006SRichard Henderson 
339a768e4e9SRichard Henderson     case INDEX_op_ctpop_i32:
340a768e4e9SRichard Henderson         return ctpop32(x);
341a768e4e9SRichard Henderson 
342a768e4e9SRichard Henderson     case INDEX_op_ctpop_i64:
343a768e4e9SRichard Henderson         return ctpop64(x);
344a768e4e9SRichard Henderson 
34525c4d9ccSRichard Henderson     CASE_OP_32_64(ext8s):
346a640f031SKirill Batuzov         return (int8_t)x;
347a640f031SKirill Batuzov 
34825c4d9ccSRichard Henderson     CASE_OP_32_64(ext16s):
349a640f031SKirill Batuzov         return (int16_t)x;
350a640f031SKirill Batuzov 
35125c4d9ccSRichard Henderson     CASE_OP_32_64(ext8u):
352a640f031SKirill Batuzov         return (uint8_t)x;
353a640f031SKirill Batuzov 
35425c4d9ccSRichard Henderson     CASE_OP_32_64(ext16u):
355a640f031SKirill Batuzov         return (uint16_t)x;
356a640f031SKirill Batuzov 
3576498594cSRichard Henderson     CASE_OP_32_64(bswap16):
3586498594cSRichard Henderson         return bswap16(x);
3596498594cSRichard Henderson 
3606498594cSRichard Henderson     CASE_OP_32_64(bswap32):
3616498594cSRichard Henderson         return bswap32(x);
3626498594cSRichard Henderson 
3636498594cSRichard Henderson     case INDEX_op_bswap64_i64:
3646498594cSRichard Henderson         return bswap64(x);
3656498594cSRichard Henderson 
3668bcb5c8fSAurelien Jarno     case INDEX_op_ext_i32_i64:
367a640f031SKirill Batuzov     case INDEX_op_ext32s_i64:
368a640f031SKirill Batuzov         return (int32_t)x;
369a640f031SKirill Batuzov 
3708bcb5c8fSAurelien Jarno     case INDEX_op_extu_i32_i64:
371609ad705SRichard Henderson     case INDEX_op_extrl_i64_i32:
372a640f031SKirill Batuzov     case INDEX_op_ext32u_i64:
373a640f031SKirill Batuzov         return (uint32_t)x;
374a640f031SKirill Batuzov 
375609ad705SRichard Henderson     case INDEX_op_extrh_i64_i32:
376609ad705SRichard Henderson         return (uint64_t)x >> 32;
377609ad705SRichard Henderson 
37803271524SRichard Henderson     case INDEX_op_muluh_i32:
37903271524SRichard Henderson         return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
38003271524SRichard Henderson     case INDEX_op_mulsh_i32:
38103271524SRichard Henderson         return ((int64_t)(int32_t)x * (int32_t)y) >> 32;
38203271524SRichard Henderson 
38303271524SRichard Henderson     case INDEX_op_muluh_i64:
38403271524SRichard Henderson         mulu64(&l64, &h64, x, y);
38503271524SRichard Henderson         return h64;
38603271524SRichard Henderson     case INDEX_op_mulsh_i64:
38703271524SRichard Henderson         muls64(&l64, &h64, x, y);
38803271524SRichard Henderson         return h64;
38903271524SRichard Henderson 
39001547f7fSRichard Henderson     case INDEX_op_div_i32:
39101547f7fSRichard Henderson         /* Avoid crashing on divide by zero, otherwise undefined.  */
39201547f7fSRichard Henderson         return (int32_t)x / ((int32_t)y ? : 1);
39301547f7fSRichard Henderson     case INDEX_op_divu_i32:
39401547f7fSRichard Henderson         return (uint32_t)x / ((uint32_t)y ? : 1);
39501547f7fSRichard Henderson     case INDEX_op_div_i64:
39601547f7fSRichard Henderson         return (int64_t)x / ((int64_t)y ? : 1);
39701547f7fSRichard Henderson     case INDEX_op_divu_i64:
39801547f7fSRichard Henderson         return (uint64_t)x / ((uint64_t)y ? : 1);
39901547f7fSRichard Henderson 
40001547f7fSRichard Henderson     case INDEX_op_rem_i32:
40101547f7fSRichard Henderson         return (int32_t)x % ((int32_t)y ? : 1);
40201547f7fSRichard Henderson     case INDEX_op_remu_i32:
40301547f7fSRichard Henderson         return (uint32_t)x % ((uint32_t)y ? : 1);
40401547f7fSRichard Henderson     case INDEX_op_rem_i64:
40501547f7fSRichard Henderson         return (int64_t)x % ((int64_t)y ? : 1);
40601547f7fSRichard Henderson     case INDEX_op_remu_i64:
40701547f7fSRichard Henderson         return (uint64_t)x % ((uint64_t)y ? : 1);
40801547f7fSRichard Henderson 
40953108fb5SKirill Batuzov     default:
41053108fb5SKirill Batuzov         fprintf(stderr,
41153108fb5SKirill Batuzov                 "Unrecognized operation %d in do_constant_folding.\n", op);
41253108fb5SKirill Batuzov         tcg_abort();
41353108fb5SKirill Batuzov     }
41453108fb5SKirill Batuzov }
41553108fb5SKirill Batuzov 
41654795544SRichard Henderson static uint64_t do_constant_folding(TCGOpcode op, uint64_t x, uint64_t y)
41753108fb5SKirill Batuzov {
418170ba88fSRichard Henderson     const TCGOpDef *def = &tcg_op_defs[op];
41954795544SRichard Henderson     uint64_t res = do_constant_folding_2(op, x, y);
420170ba88fSRichard Henderson     if (!(def->flags & TCG_OPF_64BIT)) {
42129f3ff8dSAurelien Jarno         res = (int32_t)res;
42253108fb5SKirill Batuzov     }
42353108fb5SKirill Batuzov     return res;
42453108fb5SKirill Batuzov }
42553108fb5SKirill Batuzov 
4269519da7eSRichard Henderson static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
427f8dd19e5SAurelien Jarno {
428f8dd19e5SAurelien Jarno     switch (c) {
429f8dd19e5SAurelien Jarno     case TCG_COND_EQ:
4309519da7eSRichard Henderson         return x == y;
431f8dd19e5SAurelien Jarno     case TCG_COND_NE:
4329519da7eSRichard Henderson         return x != y;
433f8dd19e5SAurelien Jarno     case TCG_COND_LT:
4349519da7eSRichard Henderson         return (int32_t)x < (int32_t)y;
435f8dd19e5SAurelien Jarno     case TCG_COND_GE:
4369519da7eSRichard Henderson         return (int32_t)x >= (int32_t)y;
437f8dd19e5SAurelien Jarno     case TCG_COND_LE:
4389519da7eSRichard Henderson         return (int32_t)x <= (int32_t)y;
439f8dd19e5SAurelien Jarno     case TCG_COND_GT:
4409519da7eSRichard Henderson         return (int32_t)x > (int32_t)y;
441f8dd19e5SAurelien Jarno     case TCG_COND_LTU:
4429519da7eSRichard Henderson         return x < y;
443f8dd19e5SAurelien Jarno     case TCG_COND_GEU:
4449519da7eSRichard Henderson         return x >= y;
445f8dd19e5SAurelien Jarno     case TCG_COND_LEU:
4469519da7eSRichard Henderson         return x <= y;
447f8dd19e5SAurelien Jarno     case TCG_COND_GTU:
4489519da7eSRichard Henderson         return x > y;
4490aed257fSRichard Henderson     default:
4509519da7eSRichard Henderson         tcg_abort();
451f8dd19e5SAurelien Jarno     }
4529519da7eSRichard Henderson }
4539519da7eSRichard Henderson 
4549519da7eSRichard Henderson static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
4559519da7eSRichard Henderson {
456f8dd19e5SAurelien Jarno     switch (c) {
457f8dd19e5SAurelien Jarno     case TCG_COND_EQ:
4589519da7eSRichard Henderson         return x == y;
459f8dd19e5SAurelien Jarno     case TCG_COND_NE:
4609519da7eSRichard Henderson         return x != y;
461f8dd19e5SAurelien Jarno     case TCG_COND_LT:
4629519da7eSRichard Henderson         return (int64_t)x < (int64_t)y;
463f8dd19e5SAurelien Jarno     case TCG_COND_GE:
4649519da7eSRichard Henderson         return (int64_t)x >= (int64_t)y;
465f8dd19e5SAurelien Jarno     case TCG_COND_LE:
4669519da7eSRichard Henderson         return (int64_t)x <= (int64_t)y;
467f8dd19e5SAurelien Jarno     case TCG_COND_GT:
4689519da7eSRichard Henderson         return (int64_t)x > (int64_t)y;
469f8dd19e5SAurelien Jarno     case TCG_COND_LTU:
4709519da7eSRichard Henderson         return x < y;
471f8dd19e5SAurelien Jarno     case TCG_COND_GEU:
4729519da7eSRichard Henderson         return x >= y;
473f8dd19e5SAurelien Jarno     case TCG_COND_LEU:
4749519da7eSRichard Henderson         return x <= y;
475f8dd19e5SAurelien Jarno     case TCG_COND_GTU:
4769519da7eSRichard Henderson         return x > y;
4770aed257fSRichard Henderson     default:
4789519da7eSRichard Henderson         tcg_abort();
479f8dd19e5SAurelien Jarno     }
480f8dd19e5SAurelien Jarno }
4819519da7eSRichard Henderson 
4829519da7eSRichard Henderson static bool do_constant_folding_cond_eq(TCGCond c)
4839519da7eSRichard Henderson {
484b336ceb6SAurelien Jarno     switch (c) {
485b336ceb6SAurelien Jarno     case TCG_COND_GT:
486b336ceb6SAurelien Jarno     case TCG_COND_LTU:
487b336ceb6SAurelien Jarno     case TCG_COND_LT:
488b336ceb6SAurelien Jarno     case TCG_COND_GTU:
489b336ceb6SAurelien Jarno     case TCG_COND_NE:
490b336ceb6SAurelien Jarno         return 0;
491b336ceb6SAurelien Jarno     case TCG_COND_GE:
492b336ceb6SAurelien Jarno     case TCG_COND_GEU:
493b336ceb6SAurelien Jarno     case TCG_COND_LE:
494b336ceb6SAurelien Jarno     case TCG_COND_LEU:
495b336ceb6SAurelien Jarno     case TCG_COND_EQ:
496b336ceb6SAurelien Jarno         return 1;
4970aed257fSRichard Henderson     default:
4989519da7eSRichard Henderson         tcg_abort();
499b336ceb6SAurelien Jarno     }
5009519da7eSRichard Henderson }
5019519da7eSRichard Henderson 
5029519da7eSRichard Henderson /* Return 2 if the condition can't be simplified, and the result
5039519da7eSRichard Henderson    of the condition (0 or 1) if it can */
5049519da7eSRichard Henderson static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
5059519da7eSRichard Henderson                                        TCGArg y, TCGCond c)
5069519da7eSRichard Henderson {
50754795544SRichard Henderson     uint64_t xv = arg_info(x)->val;
50854795544SRichard Henderson     uint64_t yv = arg_info(y)->val;
50954795544SRichard Henderson 
5106349039dSRichard Henderson     if (arg_is_const(x) && arg_is_const(y)) {
511170ba88fSRichard Henderson         const TCGOpDef *def = &tcg_op_defs[op];
512170ba88fSRichard Henderson         tcg_debug_assert(!(def->flags & TCG_OPF_VECTOR));
513170ba88fSRichard Henderson         if (def->flags & TCG_OPF_64BIT) {
5146349039dSRichard Henderson             return do_constant_folding_cond_64(xv, yv, c);
515170ba88fSRichard Henderson         } else {
516170ba88fSRichard Henderson             return do_constant_folding_cond_32(xv, yv, c);
5179519da7eSRichard Henderson         }
5186349039dSRichard Henderson     } else if (args_are_copies(x, y)) {
5199519da7eSRichard Henderson         return do_constant_folding_cond_eq(c);
5206349039dSRichard Henderson     } else if (arg_is_const(y) && yv == 0) {
521b336ceb6SAurelien Jarno         switch (c) {
522b336ceb6SAurelien Jarno         case TCG_COND_LTU:
523b336ceb6SAurelien Jarno             return 0;
524b336ceb6SAurelien Jarno         case TCG_COND_GEU:
525b336ceb6SAurelien Jarno             return 1;
526b336ceb6SAurelien Jarno         default:
527b336ceb6SAurelien Jarno             return 2;
528b336ceb6SAurelien Jarno         }
529b336ceb6SAurelien Jarno     }
530550276aeSAlex Bennée     return 2;
531f8dd19e5SAurelien Jarno }
532f8dd19e5SAurelien Jarno 
5336c4382f8SRichard Henderson /* Return 2 if the condition can't be simplified, and the result
5346c4382f8SRichard Henderson    of the condition (0 or 1) if it can */
5356c4382f8SRichard Henderson static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
5366c4382f8SRichard Henderson {
5376c4382f8SRichard Henderson     TCGArg al = p1[0], ah = p1[1];
5386c4382f8SRichard Henderson     TCGArg bl = p2[0], bh = p2[1];
5396c4382f8SRichard Henderson 
5406349039dSRichard Henderson     if (arg_is_const(bl) && arg_is_const(bh)) {
5416349039dSRichard Henderson         tcg_target_ulong blv = arg_info(bl)->val;
5426349039dSRichard Henderson         tcg_target_ulong bhv = arg_info(bh)->val;
5436349039dSRichard Henderson         uint64_t b = deposit64(blv, 32, 32, bhv);
5446c4382f8SRichard Henderson 
5456349039dSRichard Henderson         if (arg_is_const(al) && arg_is_const(ah)) {
5466349039dSRichard Henderson             tcg_target_ulong alv = arg_info(al)->val;
5476349039dSRichard Henderson             tcg_target_ulong ahv = arg_info(ah)->val;
5486349039dSRichard Henderson             uint64_t a = deposit64(alv, 32, 32, ahv);
5496c4382f8SRichard Henderson             return do_constant_folding_cond_64(a, b, c);
5506c4382f8SRichard Henderson         }
5516c4382f8SRichard Henderson         if (b == 0) {
5526c4382f8SRichard Henderson             switch (c) {
5536c4382f8SRichard Henderson             case TCG_COND_LTU:
5546c4382f8SRichard Henderson                 return 0;
5556c4382f8SRichard Henderson             case TCG_COND_GEU:
5566c4382f8SRichard Henderson                 return 1;
5576c4382f8SRichard Henderson             default:
5586c4382f8SRichard Henderson                 break;
5596c4382f8SRichard Henderson             }
5606c4382f8SRichard Henderson         }
5616c4382f8SRichard Henderson     }
5626349039dSRichard Henderson     if (args_are_copies(al, bl) && args_are_copies(ah, bh)) {
5636c4382f8SRichard Henderson         return do_constant_folding_cond_eq(c);
5646c4382f8SRichard Henderson     }
5656c4382f8SRichard Henderson     return 2;
5666c4382f8SRichard Henderson }
5676c4382f8SRichard Henderson 
56824c9ae4eSRichard Henderson static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
56924c9ae4eSRichard Henderson {
57024c9ae4eSRichard Henderson     TCGArg a1 = *p1, a2 = *p2;
57124c9ae4eSRichard Henderson     int sum = 0;
5726349039dSRichard Henderson     sum += arg_is_const(a1);
5736349039dSRichard Henderson     sum -= arg_is_const(a2);
57424c9ae4eSRichard Henderson 
57524c9ae4eSRichard Henderson     /* Prefer the constant in second argument, and then the form
57624c9ae4eSRichard Henderson        op a, a, b, which is better handled on non-RISC hosts. */
57724c9ae4eSRichard Henderson     if (sum > 0 || (sum == 0 && dest == a2)) {
57824c9ae4eSRichard Henderson         *p1 = a2;
57924c9ae4eSRichard Henderson         *p2 = a1;
58024c9ae4eSRichard Henderson         return true;
58124c9ae4eSRichard Henderson     }
58224c9ae4eSRichard Henderson     return false;
58324c9ae4eSRichard Henderson }
58424c9ae4eSRichard Henderson 
5850bfcb865SRichard Henderson static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
5860bfcb865SRichard Henderson {
5870bfcb865SRichard Henderson     int sum = 0;
5886349039dSRichard Henderson     sum += arg_is_const(p1[0]);
5896349039dSRichard Henderson     sum += arg_is_const(p1[1]);
5906349039dSRichard Henderson     sum -= arg_is_const(p2[0]);
5916349039dSRichard Henderson     sum -= arg_is_const(p2[1]);
5920bfcb865SRichard Henderson     if (sum > 0) {
5930bfcb865SRichard Henderson         TCGArg t;
5940bfcb865SRichard Henderson         t = p1[0], p1[0] = p2[0], p2[0] = t;
5950bfcb865SRichard Henderson         t = p1[1], p1[1] = p2[1], p2[1] = t;
5960bfcb865SRichard Henderson         return true;
5970bfcb865SRichard Henderson     }
5980bfcb865SRichard Henderson     return false;
5990bfcb865SRichard Henderson }
6000bfcb865SRichard Henderson 
60122613af4SKirill Batuzov /* Propagate constants and copies, fold constant expressions. */
60236e60ef6SAurelien Jarno void tcg_optimize(TCGContext *s)
6038f2e8c07SKirill Batuzov {
6048f17a975SRichard Henderson     int nb_temps, nb_globals, i;
60515fa08f8SRichard Henderson     TCGOp *op, *op_next, *prev_mb = NULL;
60634184b07SEmilio G. Cota     TCGTempSet temps_used;
6075d8f5363SRichard Henderson 
60822613af4SKirill Batuzov     /* Array VALS has an element for each temp.
60922613af4SKirill Batuzov        If this temp holds a constant then its value is kept in VALS' element.
610e590d4e6SAurelien Jarno        If this temp is a copy of other ones then the other copies are
611e590d4e6SAurelien Jarno        available through the doubly linked circular list. */
6128f2e8c07SKirill Batuzov 
6138f2e8c07SKirill Batuzov     nb_temps = s->nb_temps;
6148f2e8c07SKirill Batuzov     nb_globals = s->nb_globals;
6158f17a975SRichard Henderson 
6168fe35e04SRichard Henderson     memset(&temps_used, 0, sizeof(temps_used));
6178f17a975SRichard Henderson     for (i = 0; i < nb_temps; ++i) {
6188f17a975SRichard Henderson         s->temps[i].state_ptr = NULL;
6198f17a975SRichard Henderson     }
6208f2e8c07SKirill Batuzov 
62115fa08f8SRichard Henderson     QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) {
62254795544SRichard Henderson         uint64_t mask, partmask, affected, tmp;
6238f17a975SRichard Henderson         int nb_oargs, nb_iargs;
624c45cb8bbSRichard Henderson         TCGOpcode opc = op->opc;
625c45cb8bbSRichard Henderson         const TCGOpDef *def = &tcg_op_defs[opc];
626c45cb8bbSRichard Henderson 
6271208d7ddSAurelien Jarno         /* Count the arguments, and initialize the temps that are
6281208d7ddSAurelien Jarno            going to be used */
629c45cb8bbSRichard Henderson         if (opc == INDEX_op_call) {
630cd9090aaSRichard Henderson             nb_oargs = TCGOP_CALLO(op);
631cd9090aaSRichard Henderson             nb_iargs = TCGOP_CALLI(op);
6321208d7ddSAurelien Jarno             for (i = 0; i < nb_oargs + nb_iargs; i++) {
6336349039dSRichard Henderson                 TCGTemp *ts = arg_temp(op->args[i]);
6346349039dSRichard Henderson                 if (ts) {
6358f17a975SRichard Henderson                     init_ts_info(&temps_used, ts);
6361208d7ddSAurelien Jarno                 }
6371208d7ddSAurelien Jarno             }
6381ff8c541SAurelien Jarno         } else {
639cf066674SRichard Henderson             nb_oargs = def->nb_oargs;
640cf066674SRichard Henderson             nb_iargs = def->nb_iargs;
6411208d7ddSAurelien Jarno             for (i = 0; i < nb_oargs + nb_iargs; i++) {
6428f17a975SRichard Henderson                 init_arg_info(&temps_used, op->args[i]);
6431208d7ddSAurelien Jarno             }
644cf066674SRichard Henderson         }
645cf066674SRichard Henderson 
646cf066674SRichard Henderson         /* Do copy propagation */
647cf066674SRichard Henderson         for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
6486349039dSRichard Henderson             TCGTemp *ts = arg_temp(op->args[i]);
6496349039dSRichard Henderson             if (ts && ts_is_copy(ts)) {
6506349039dSRichard Henderson                 op->args[i] = temp_arg(find_better_copy(s, ts));
65122613af4SKirill Batuzov             }
65222613af4SKirill Batuzov         }
65322613af4SKirill Batuzov 
65453108fb5SKirill Batuzov         /* For commutative operations make constant second argument */
655c45cb8bbSRichard Henderson         switch (opc) {
656170ba88fSRichard Henderson         CASE_OP_32_64_VEC(add):
657170ba88fSRichard Henderson         CASE_OP_32_64_VEC(mul):
658170ba88fSRichard Henderson         CASE_OP_32_64_VEC(and):
659170ba88fSRichard Henderson         CASE_OP_32_64_VEC(or):
660170ba88fSRichard Henderson         CASE_OP_32_64_VEC(xor):
661cb25c80aSRichard Henderson         CASE_OP_32_64(eqv):
662cb25c80aSRichard Henderson         CASE_OP_32_64(nand):
663cb25c80aSRichard Henderson         CASE_OP_32_64(nor):
66403271524SRichard Henderson         CASE_OP_32_64(muluh):
66503271524SRichard Henderson         CASE_OP_32_64(mulsh):
666acd93701SRichard Henderson             swap_commutative(op->args[0], &op->args[1], &op->args[2]);
66753108fb5SKirill Batuzov             break;
66865a7cce1SAurelien Jarno         CASE_OP_32_64(brcond):
669acd93701SRichard Henderson             if (swap_commutative(-1, &op->args[0], &op->args[1])) {
670acd93701SRichard Henderson                 op->args[2] = tcg_swap_cond(op->args[2]);
67165a7cce1SAurelien Jarno             }
67265a7cce1SAurelien Jarno             break;
67365a7cce1SAurelien Jarno         CASE_OP_32_64(setcond):
674acd93701SRichard Henderson             if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) {
675acd93701SRichard Henderson                 op->args[3] = tcg_swap_cond(op->args[3]);
67665a7cce1SAurelien Jarno             }
67765a7cce1SAurelien Jarno             break;
678fa01a208SRichard Henderson         CASE_OP_32_64(movcond):
679acd93701SRichard Henderson             if (swap_commutative(-1, &op->args[1], &op->args[2])) {
680acd93701SRichard Henderson                 op->args[5] = tcg_swap_cond(op->args[5]);
681fa01a208SRichard Henderson             }
6825d8f5363SRichard Henderson             /* For movcond, we canonicalize the "false" input reg to match
6835d8f5363SRichard Henderson                the destination reg so that the tcg backend can implement
6845d8f5363SRichard Henderson                a "move if true" operation.  */
685acd93701SRichard Henderson             if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) {
686acd93701SRichard Henderson                 op->args[5] = tcg_invert_cond(op->args[5]);
6875d8f5363SRichard Henderson             }
6881e484e61SRichard Henderson             break;
689d7156f7cSRichard Henderson         CASE_OP_32_64(add2):
690acd93701SRichard Henderson             swap_commutative(op->args[0], &op->args[2], &op->args[4]);
691acd93701SRichard Henderson             swap_commutative(op->args[1], &op->args[3], &op->args[5]);
6921e484e61SRichard Henderson             break;
693d7156f7cSRichard Henderson         CASE_OP_32_64(mulu2):
6944d3203fdSRichard Henderson         CASE_OP_32_64(muls2):
695acd93701SRichard Henderson             swap_commutative(op->args[0], &op->args[2], &op->args[3]);
6961414968aSRichard Henderson             break;
6970bfcb865SRichard Henderson         case INDEX_op_brcond2_i32:
698acd93701SRichard Henderson             if (swap_commutative2(&op->args[0], &op->args[2])) {
699acd93701SRichard Henderson                 op->args[4] = tcg_swap_cond(op->args[4]);
7000bfcb865SRichard Henderson             }
7010bfcb865SRichard Henderson             break;
7020bfcb865SRichard Henderson         case INDEX_op_setcond2_i32:
703acd93701SRichard Henderson             if (swap_commutative2(&op->args[1], &op->args[3])) {
704acd93701SRichard Henderson                 op->args[5] = tcg_swap_cond(op->args[5]);
7050bfcb865SRichard Henderson             }
7060bfcb865SRichard Henderson             break;
70753108fb5SKirill Batuzov         default:
70853108fb5SKirill Batuzov             break;
70953108fb5SKirill Batuzov         }
71053108fb5SKirill Batuzov 
7112d497542SRichard Henderson         /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
7122d497542SRichard Henderson            and "sub r, 0, a => neg r, a" case.  */
713c45cb8bbSRichard Henderson         switch (opc) {
71401ee5282SAurelien Jarno         CASE_OP_32_64(shl):
71501ee5282SAurelien Jarno         CASE_OP_32_64(shr):
71601ee5282SAurelien Jarno         CASE_OP_32_64(sar):
71701ee5282SAurelien Jarno         CASE_OP_32_64(rotl):
71801ee5282SAurelien Jarno         CASE_OP_32_64(rotr):
7196349039dSRichard Henderson             if (arg_is_const(op->args[1])
7206349039dSRichard Henderson                 && arg_info(op->args[1])->val == 0) {
7218fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], 0);
72201ee5282SAurelien Jarno                 continue;
72301ee5282SAurelien Jarno             }
72401ee5282SAurelien Jarno             break;
725170ba88fSRichard Henderson         CASE_OP_32_64_VEC(sub):
7262d497542SRichard Henderson             {
7272d497542SRichard Henderson                 TCGOpcode neg_op;
7282d497542SRichard Henderson                 bool have_neg;
7292d497542SRichard Henderson 
7306349039dSRichard Henderson                 if (arg_is_const(op->args[2])) {
7312d497542SRichard Henderson                     /* Proceed with possible constant folding. */
7322d497542SRichard Henderson                     break;
7332d497542SRichard Henderson                 }
734c45cb8bbSRichard Henderson                 if (opc == INDEX_op_sub_i32) {
7352d497542SRichard Henderson                     neg_op = INDEX_op_neg_i32;
7362d497542SRichard Henderson                     have_neg = TCG_TARGET_HAS_neg_i32;
737170ba88fSRichard Henderson                 } else if (opc == INDEX_op_sub_i64) {
7382d497542SRichard Henderson                     neg_op = INDEX_op_neg_i64;
7392d497542SRichard Henderson                     have_neg = TCG_TARGET_HAS_neg_i64;
740ac383ddeSRichard Henderson                 } else if (TCG_TARGET_HAS_neg_vec) {
741ac383ddeSRichard Henderson                     TCGType type = TCGOP_VECL(op) + TCG_TYPE_V64;
742ac383ddeSRichard Henderson                     unsigned vece = TCGOP_VECE(op);
743170ba88fSRichard Henderson                     neg_op = INDEX_op_neg_vec;
744ac383ddeSRichard Henderson                     have_neg = tcg_can_emit_vec_op(neg_op, type, vece) > 0;
745ac383ddeSRichard Henderson                 } else {
746ac383ddeSRichard Henderson                     break;
7472d497542SRichard Henderson                 }
7482d497542SRichard Henderson                 if (!have_neg) {
7492d497542SRichard Henderson                     break;
7502d497542SRichard Henderson                 }
7516349039dSRichard Henderson                 if (arg_is_const(op->args[1])
7526349039dSRichard Henderson                     && arg_info(op->args[1])->val == 0) {
753c45cb8bbSRichard Henderson                     op->opc = neg_op;
754acd93701SRichard Henderson                     reset_temp(op->args[0]);
755acd93701SRichard Henderson                     op->args[1] = op->args[2];
7562d497542SRichard Henderson                     continue;
7572d497542SRichard Henderson                 }
7582d497542SRichard Henderson             }
7592d497542SRichard Henderson             break;
760170ba88fSRichard Henderson         CASE_OP_32_64_VEC(xor):
761e201b564SRichard Henderson         CASE_OP_32_64(nand):
7626349039dSRichard Henderson             if (!arg_is_const(op->args[1])
7636349039dSRichard Henderson                 && arg_is_const(op->args[2])
7646349039dSRichard Henderson                 && arg_info(op->args[2])->val == -1) {
765e201b564SRichard Henderson                 i = 1;
766e201b564SRichard Henderson                 goto try_not;
767e201b564SRichard Henderson             }
768e201b564SRichard Henderson             break;
769e201b564SRichard Henderson         CASE_OP_32_64(nor):
7706349039dSRichard Henderson             if (!arg_is_const(op->args[1])
7716349039dSRichard Henderson                 && arg_is_const(op->args[2])
7726349039dSRichard Henderson                 && arg_info(op->args[2])->val == 0) {
773e201b564SRichard Henderson                 i = 1;
774e201b564SRichard Henderson                 goto try_not;
775e201b564SRichard Henderson             }
776e201b564SRichard Henderson             break;
777170ba88fSRichard Henderson         CASE_OP_32_64_VEC(andc):
7786349039dSRichard Henderson             if (!arg_is_const(op->args[2])
7796349039dSRichard Henderson                 && arg_is_const(op->args[1])
7806349039dSRichard Henderson                 && arg_info(op->args[1])->val == -1) {
781e201b564SRichard Henderson                 i = 2;
782e201b564SRichard Henderson                 goto try_not;
783e201b564SRichard Henderson             }
784e201b564SRichard Henderson             break;
785170ba88fSRichard Henderson         CASE_OP_32_64_VEC(orc):
786e201b564SRichard Henderson         CASE_OP_32_64(eqv):
7876349039dSRichard Henderson             if (!arg_is_const(op->args[2])
7886349039dSRichard Henderson                 && arg_is_const(op->args[1])
7896349039dSRichard Henderson                 && arg_info(op->args[1])->val == 0) {
790e201b564SRichard Henderson                 i = 2;
791e201b564SRichard Henderson                 goto try_not;
792e201b564SRichard Henderson             }
793e201b564SRichard Henderson             break;
794e201b564SRichard Henderson         try_not:
795e201b564SRichard Henderson             {
796e201b564SRichard Henderson                 TCGOpcode not_op;
797e201b564SRichard Henderson                 bool have_not;
798e201b564SRichard Henderson 
799170ba88fSRichard Henderson                 if (def->flags & TCG_OPF_VECTOR) {
800170ba88fSRichard Henderson                     not_op = INDEX_op_not_vec;
801170ba88fSRichard Henderson                     have_not = TCG_TARGET_HAS_not_vec;
802170ba88fSRichard Henderson                 } else if (def->flags & TCG_OPF_64BIT) {
803e201b564SRichard Henderson                     not_op = INDEX_op_not_i64;
804e201b564SRichard Henderson                     have_not = TCG_TARGET_HAS_not_i64;
805e201b564SRichard Henderson                 } else {
806e201b564SRichard Henderson                     not_op = INDEX_op_not_i32;
807e201b564SRichard Henderson                     have_not = TCG_TARGET_HAS_not_i32;
808e201b564SRichard Henderson                 }
809e201b564SRichard Henderson                 if (!have_not) {
810e201b564SRichard Henderson                     break;
811e201b564SRichard Henderson                 }
812c45cb8bbSRichard Henderson                 op->opc = not_op;
813acd93701SRichard Henderson                 reset_temp(op->args[0]);
814acd93701SRichard Henderson                 op->args[1] = op->args[i];
815e201b564SRichard Henderson                 continue;
816e201b564SRichard Henderson             }
81701ee5282SAurelien Jarno         default:
81801ee5282SAurelien Jarno             break;
81901ee5282SAurelien Jarno         }
82001ee5282SAurelien Jarno 
821464a1441SRichard Henderson         /* Simplify expression for "op r, a, const => mov r, a" cases */
822c45cb8bbSRichard Henderson         switch (opc) {
823170ba88fSRichard Henderson         CASE_OP_32_64_VEC(add):
824170ba88fSRichard Henderson         CASE_OP_32_64_VEC(sub):
825170ba88fSRichard Henderson         CASE_OP_32_64_VEC(or):
826170ba88fSRichard Henderson         CASE_OP_32_64_VEC(xor):
827170ba88fSRichard Henderson         CASE_OP_32_64_VEC(andc):
82855c0975cSKirill Batuzov         CASE_OP_32_64(shl):
82955c0975cSKirill Batuzov         CASE_OP_32_64(shr):
83055c0975cSKirill Batuzov         CASE_OP_32_64(sar):
83125c4d9ccSRichard Henderson         CASE_OP_32_64(rotl):
83225c4d9ccSRichard Henderson         CASE_OP_32_64(rotr):
8336349039dSRichard Henderson             if (!arg_is_const(op->args[1])
8346349039dSRichard Henderson                 && arg_is_const(op->args[2])
8356349039dSRichard Henderson                 && arg_info(op->args[2])->val == 0) {
836acd93701SRichard Henderson                 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
83797a79eb7SAurelien Jarno                 continue;
838464a1441SRichard Henderson             }
839464a1441SRichard Henderson             break;
840170ba88fSRichard Henderson         CASE_OP_32_64_VEC(and):
841170ba88fSRichard Henderson         CASE_OP_32_64_VEC(orc):
842464a1441SRichard Henderson         CASE_OP_32_64(eqv):
8436349039dSRichard Henderson             if (!arg_is_const(op->args[1])
8446349039dSRichard Henderson                 && arg_is_const(op->args[2])
8456349039dSRichard Henderson                 && arg_info(op->args[2])->val == -1) {
846acd93701SRichard Henderson                 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
84753108fb5SKirill Batuzov                 continue;
84897a79eb7SAurelien Jarno             }
84997a79eb7SAurelien Jarno             break;
85056e49438SAurelien Jarno         default:
85156e49438SAurelien Jarno             break;
85256e49438SAurelien Jarno         }
85356e49438SAurelien Jarno 
8543031244bSAurelien Jarno         /* Simplify using known-zero bits. Currently only ops with a single
8553031244bSAurelien Jarno            output argument is supported. */
8563a9d8b17SPaolo Bonzini         mask = -1;
857633f6502SPaolo Bonzini         affected = -1;
858c45cb8bbSRichard Henderson         switch (opc) {
8593a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext8s):
8606349039dSRichard Henderson             if ((arg_info(op->args[1])->mask & 0x80) != 0) {
8613a9d8b17SPaolo Bonzini                 break;
8623a9d8b17SPaolo Bonzini             }
863d84568b7SThomas Huth             QEMU_FALLTHROUGH;
8643a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext8u):
8653a9d8b17SPaolo Bonzini             mask = 0xff;
8663a9d8b17SPaolo Bonzini             goto and_const;
8673a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext16s):
8686349039dSRichard Henderson             if ((arg_info(op->args[1])->mask & 0x8000) != 0) {
8693a9d8b17SPaolo Bonzini                 break;
8703a9d8b17SPaolo Bonzini             }
871d84568b7SThomas Huth             QEMU_FALLTHROUGH;
8723a9d8b17SPaolo Bonzini         CASE_OP_32_64(ext16u):
8733a9d8b17SPaolo Bonzini             mask = 0xffff;
8743a9d8b17SPaolo Bonzini             goto and_const;
8753a9d8b17SPaolo Bonzini         case INDEX_op_ext32s_i64:
8766349039dSRichard Henderson             if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
8773a9d8b17SPaolo Bonzini                 break;
8783a9d8b17SPaolo Bonzini             }
879d84568b7SThomas Huth             QEMU_FALLTHROUGH;
8803a9d8b17SPaolo Bonzini         case INDEX_op_ext32u_i64:
8813a9d8b17SPaolo Bonzini             mask = 0xffffffffU;
8823a9d8b17SPaolo Bonzini             goto and_const;
8833a9d8b17SPaolo Bonzini 
8843a9d8b17SPaolo Bonzini         CASE_OP_32_64(and):
8856349039dSRichard Henderson             mask = arg_info(op->args[2])->mask;
8866349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
8873a9d8b17SPaolo Bonzini         and_const:
8886349039dSRichard Henderson                 affected = arg_info(op->args[1])->mask & ~mask;
8893a9d8b17SPaolo Bonzini             }
8906349039dSRichard Henderson             mask = arg_info(op->args[1])->mask & mask;
8913a9d8b17SPaolo Bonzini             break;
8923a9d8b17SPaolo Bonzini 
8938bcb5c8fSAurelien Jarno         case INDEX_op_ext_i32_i64:
8946349039dSRichard Henderson             if ((arg_info(op->args[1])->mask & 0x80000000) != 0) {
8958bcb5c8fSAurelien Jarno                 break;
8968bcb5c8fSAurelien Jarno             }
897d84568b7SThomas Huth             QEMU_FALLTHROUGH;
8988bcb5c8fSAurelien Jarno         case INDEX_op_extu_i32_i64:
8998bcb5c8fSAurelien Jarno             /* We do not compute affected as it is a size changing op.  */
9006349039dSRichard Henderson             mask = (uint32_t)arg_info(op->args[1])->mask;
9018bcb5c8fSAurelien Jarno             break;
9028bcb5c8fSAurelien Jarno 
90323ec69edSRichard Henderson         CASE_OP_32_64(andc):
90423ec69edSRichard Henderson             /* Known-zeros does not imply known-ones.  Therefore unless
905acd93701SRichard Henderson                op->args[2] is constant, we can't infer anything from it.  */
9066349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
9076349039dSRichard Henderson                 mask = ~arg_info(op->args[2])->mask;
90823ec69edSRichard Henderson                 goto and_const;
90923ec69edSRichard Henderson             }
9106349039dSRichard Henderson             /* But we certainly know nothing outside args[1] may be set. */
9116349039dSRichard Henderson             mask = arg_info(op->args[1])->mask;
91223ec69edSRichard Henderson             break;
91323ec69edSRichard Henderson 
914e46b225aSAurelien Jarno         case INDEX_op_sar_i32:
9156349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
9166349039dSRichard Henderson                 tmp = arg_info(op->args[2])->val & 31;
9176349039dSRichard Henderson                 mask = (int32_t)arg_info(op->args[1])->mask >> tmp;
918e46b225aSAurelien Jarno             }
919e46b225aSAurelien Jarno             break;
920e46b225aSAurelien Jarno         case INDEX_op_sar_i64:
9216349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
9226349039dSRichard Henderson                 tmp = arg_info(op->args[2])->val & 63;
9236349039dSRichard Henderson                 mask = (int64_t)arg_info(op->args[1])->mask >> tmp;
9243a9d8b17SPaolo Bonzini             }
9253a9d8b17SPaolo Bonzini             break;
9263a9d8b17SPaolo Bonzini 
927e46b225aSAurelien Jarno         case INDEX_op_shr_i32:
9286349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
9296349039dSRichard Henderson                 tmp = arg_info(op->args[2])->val & 31;
9306349039dSRichard Henderson                 mask = (uint32_t)arg_info(op->args[1])->mask >> tmp;
931e46b225aSAurelien Jarno             }
932e46b225aSAurelien Jarno             break;
933e46b225aSAurelien Jarno         case INDEX_op_shr_i64:
9346349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
9356349039dSRichard Henderson                 tmp = arg_info(op->args[2])->val & 63;
9366349039dSRichard Henderson                 mask = (uint64_t)arg_info(op->args[1])->mask >> tmp;
9373a9d8b17SPaolo Bonzini             }
9383a9d8b17SPaolo Bonzini             break;
9393a9d8b17SPaolo Bonzini 
940609ad705SRichard Henderson         case INDEX_op_extrl_i64_i32:
9416349039dSRichard Henderson             mask = (uint32_t)arg_info(op->args[1])->mask;
942609ad705SRichard Henderson             break;
943609ad705SRichard Henderson         case INDEX_op_extrh_i64_i32:
9446349039dSRichard Henderson             mask = (uint64_t)arg_info(op->args[1])->mask >> 32;
9454bb7a41eSRichard Henderson             break;
9464bb7a41eSRichard Henderson 
9473a9d8b17SPaolo Bonzini         CASE_OP_32_64(shl):
9486349039dSRichard Henderson             if (arg_is_const(op->args[2])) {
9496349039dSRichard Henderson                 tmp = arg_info(op->args[2])->val & (TCG_TARGET_REG_BITS - 1);
9506349039dSRichard Henderson                 mask = arg_info(op->args[1])->mask << tmp;
9513a9d8b17SPaolo Bonzini             }
9523a9d8b17SPaolo Bonzini             break;
9533a9d8b17SPaolo Bonzini 
9543a9d8b17SPaolo Bonzini         CASE_OP_32_64(neg):
9553a9d8b17SPaolo Bonzini             /* Set to 1 all bits to the left of the rightmost.  */
9566349039dSRichard Henderson             mask = -(arg_info(op->args[1])->mask
9576349039dSRichard Henderson                      & -arg_info(op->args[1])->mask);
9583a9d8b17SPaolo Bonzini             break;
9593a9d8b17SPaolo Bonzini 
9603a9d8b17SPaolo Bonzini         CASE_OP_32_64(deposit):
9616349039dSRichard Henderson             mask = deposit64(arg_info(op->args[1])->mask,
9626349039dSRichard Henderson                              op->args[3], op->args[4],
9636349039dSRichard Henderson                              arg_info(op->args[2])->mask);
9643a9d8b17SPaolo Bonzini             break;
9653a9d8b17SPaolo Bonzini 
9667ec8bab3SRichard Henderson         CASE_OP_32_64(extract):
9676349039dSRichard Henderson             mask = extract64(arg_info(op->args[1])->mask,
9686349039dSRichard Henderson                              op->args[2], op->args[3]);
969acd93701SRichard Henderson             if (op->args[2] == 0) {
9706349039dSRichard Henderson                 affected = arg_info(op->args[1])->mask & ~mask;
9717ec8bab3SRichard Henderson             }
9727ec8bab3SRichard Henderson             break;
9737ec8bab3SRichard Henderson         CASE_OP_32_64(sextract):
9746349039dSRichard Henderson             mask = sextract64(arg_info(op->args[1])->mask,
975acd93701SRichard Henderson                               op->args[2], op->args[3]);
976acd93701SRichard Henderson             if (op->args[2] == 0 && (tcg_target_long)mask >= 0) {
9776349039dSRichard Henderson                 affected = arg_info(op->args[1])->mask & ~mask;
9787ec8bab3SRichard Henderson             }
9797ec8bab3SRichard Henderson             break;
9807ec8bab3SRichard Henderson 
9813a9d8b17SPaolo Bonzini         CASE_OP_32_64(or):
9823a9d8b17SPaolo Bonzini         CASE_OP_32_64(xor):
9836349039dSRichard Henderson             mask = arg_info(op->args[1])->mask | arg_info(op->args[2])->mask;
9843a9d8b17SPaolo Bonzini             break;
9853a9d8b17SPaolo Bonzini 
9860e28d006SRichard Henderson         case INDEX_op_clz_i32:
9870e28d006SRichard Henderson         case INDEX_op_ctz_i32:
9886349039dSRichard Henderson             mask = arg_info(op->args[2])->mask | 31;
9890e28d006SRichard Henderson             break;
9900e28d006SRichard Henderson 
9910e28d006SRichard Henderson         case INDEX_op_clz_i64:
9920e28d006SRichard Henderson         case INDEX_op_ctz_i64:
9936349039dSRichard Henderson             mask = arg_info(op->args[2])->mask | 63;
9940e28d006SRichard Henderson             break;
9950e28d006SRichard Henderson 
996a768e4e9SRichard Henderson         case INDEX_op_ctpop_i32:
997a768e4e9SRichard Henderson             mask = 32 | 31;
998a768e4e9SRichard Henderson             break;
999a768e4e9SRichard Henderson         case INDEX_op_ctpop_i64:
1000a768e4e9SRichard Henderson             mask = 64 | 63;
1001a768e4e9SRichard Henderson             break;
1002a768e4e9SRichard Henderson 
10033a9d8b17SPaolo Bonzini         CASE_OP_32_64(setcond):
1004a763551aSRichard Henderson         case INDEX_op_setcond2_i32:
10053a9d8b17SPaolo Bonzini             mask = 1;
10063a9d8b17SPaolo Bonzini             break;
10073a9d8b17SPaolo Bonzini 
10083a9d8b17SPaolo Bonzini         CASE_OP_32_64(movcond):
10096349039dSRichard Henderson             mask = arg_info(op->args[3])->mask | arg_info(op->args[4])->mask;
10103a9d8b17SPaolo Bonzini             break;
10113a9d8b17SPaolo Bonzini 
1012c8d70272SAurelien Jarno         CASE_OP_32_64(ld8u):
1013c8d70272SAurelien Jarno             mask = 0xff;
1014c8d70272SAurelien Jarno             break;
1015c8d70272SAurelien Jarno         CASE_OP_32_64(ld16u):
1016c8d70272SAurelien Jarno             mask = 0xffff;
1017c8d70272SAurelien Jarno             break;
1018c8d70272SAurelien Jarno         case INDEX_op_ld32u_i64:
1019c8d70272SAurelien Jarno             mask = 0xffffffffu;
1020c8d70272SAurelien Jarno             break;
1021c8d70272SAurelien Jarno 
1022c8d70272SAurelien Jarno         CASE_OP_32_64(qemu_ld):
1023c8d70272SAurelien Jarno             {
1024acd93701SRichard Henderson                 TCGMemOpIdx oi = op->args[nb_oargs + nb_iargs];
102514776ab5STony Nguyen                 MemOp mop = get_memop(oi);
1026c8d70272SAurelien Jarno                 if (!(mop & MO_SIGN)) {
1027c8d70272SAurelien Jarno                     mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
1028c8d70272SAurelien Jarno                 }
1029c8d70272SAurelien Jarno             }
1030c8d70272SAurelien Jarno             break;
1031c8d70272SAurelien Jarno 
10323a9d8b17SPaolo Bonzini         default:
10333a9d8b17SPaolo Bonzini             break;
10343a9d8b17SPaolo Bonzini         }
10353a9d8b17SPaolo Bonzini 
1036bc8d688fSRichard Henderson         /* 32-bit ops generate 32-bit results.  For the result is zero test
1037bc8d688fSRichard Henderson            below, we can ignore high bits, but for further optimizations we
1038bc8d688fSRichard Henderson            need to record that the high bits contain garbage.  */
103924666bafSRichard Henderson         partmask = mask;
1040bc8d688fSRichard Henderson         if (!(def->flags & TCG_OPF_64BIT)) {
104124666bafSRichard Henderson             mask |= ~(tcg_target_ulong)0xffffffffu;
104224666bafSRichard Henderson             partmask &= 0xffffffffu;
104324666bafSRichard Henderson             affected &= 0xffffffffu;
1044f096dc96SAurelien Jarno         }
1045f096dc96SAurelien Jarno 
104624666bafSRichard Henderson         if (partmask == 0) {
1047eabb7b91SAurelien Jarno             tcg_debug_assert(nb_oargs == 1);
10488fe35e04SRichard Henderson             tcg_opt_gen_movi(s, &temps_used, op, op->args[0], 0);
1049633f6502SPaolo Bonzini             continue;
1050633f6502SPaolo Bonzini         }
1051633f6502SPaolo Bonzini         if (affected == 0) {
1052eabb7b91SAurelien Jarno             tcg_debug_assert(nb_oargs == 1);
1053acd93701SRichard Henderson             tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
1054633f6502SPaolo Bonzini             continue;
1055633f6502SPaolo Bonzini         }
1056633f6502SPaolo Bonzini 
105756e49438SAurelien Jarno         /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
1058c45cb8bbSRichard Henderson         switch (opc) {
1059170ba88fSRichard Henderson         CASE_OP_32_64_VEC(and):
1060170ba88fSRichard Henderson         CASE_OP_32_64_VEC(mul):
106103271524SRichard Henderson         CASE_OP_32_64(muluh):
106203271524SRichard Henderson         CASE_OP_32_64(mulsh):
10636349039dSRichard Henderson             if (arg_is_const(op->args[2])
10646349039dSRichard Henderson                 && arg_info(op->args[2])->val == 0) {
10658fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], 0);
106653108fb5SKirill Batuzov                 continue;
106753108fb5SKirill Batuzov             }
106853108fb5SKirill Batuzov             break;
106956e49438SAurelien Jarno         default:
107056e49438SAurelien Jarno             break;
107156e49438SAurelien Jarno         }
107256e49438SAurelien Jarno 
107356e49438SAurelien Jarno         /* Simplify expression for "op r, a, a => mov r, a" cases */
1074c45cb8bbSRichard Henderson         switch (opc) {
1075170ba88fSRichard Henderson         CASE_OP_32_64_VEC(or):
1076170ba88fSRichard Henderson         CASE_OP_32_64_VEC(and):
10776349039dSRichard Henderson             if (args_are_copies(op->args[1], op->args[2])) {
1078acd93701SRichard Henderson                 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
10799a81090bSKirill Batuzov                 continue;
10809a81090bSKirill Batuzov             }
10819a81090bSKirill Batuzov             break;
1082fe0de7aaSBlue Swirl         default:
1083fe0de7aaSBlue Swirl             break;
108453108fb5SKirill Batuzov         }
108553108fb5SKirill Batuzov 
10863c94193eSAurelien Jarno         /* Simplify expression for "op r, a, a => movi r, 0" cases */
1087c45cb8bbSRichard Henderson         switch (opc) {
1088170ba88fSRichard Henderson         CASE_OP_32_64_VEC(andc):
1089170ba88fSRichard Henderson         CASE_OP_32_64_VEC(sub):
1090170ba88fSRichard Henderson         CASE_OP_32_64_VEC(xor):
10916349039dSRichard Henderson             if (args_are_copies(op->args[1], op->args[2])) {
10928fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], 0);
10933c94193eSAurelien Jarno                 continue;
10943c94193eSAurelien Jarno             }
10953c94193eSAurelien Jarno             break;
10963c94193eSAurelien Jarno         default:
10973c94193eSAurelien Jarno             break;
10983c94193eSAurelien Jarno         }
10993c94193eSAurelien Jarno 
110022613af4SKirill Batuzov         /* Propagate constants through copy operations and do constant
110122613af4SKirill Batuzov            folding.  Constants will be substituted to arguments by register
110222613af4SKirill Batuzov            allocator where needed and possible.  Also detect copies. */
1103c45cb8bbSRichard Henderson         switch (opc) {
1104170ba88fSRichard Henderson         CASE_OP_32_64_VEC(mov):
1105acd93701SRichard Henderson             tcg_opt_gen_mov(s, op, op->args[0], op->args[1]);
110622613af4SKirill Batuzov             break;
11076e14e91bSRichard Henderson 
1108170ba88fSRichard Henderson         case INDEX_op_dup_vec:
1109170ba88fSRichard Henderson             if (arg_is_const(op->args[1])) {
1110170ba88fSRichard Henderson                 tmp = arg_info(op->args[1])->val;
1111170ba88fSRichard Henderson                 tmp = dup_const(TCGOP_VECE(op), tmp);
11128fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
1113170ba88fSRichard Henderson                 break;
11141fb57da7SRichard Henderson             }
11151fb57da7SRichard Henderson             goto do_default;
1116170ba88fSRichard Henderson 
11171dc4fe70SRichard Henderson         case INDEX_op_dup2_vec:
11181dc4fe70SRichard Henderson             assert(TCG_TARGET_REG_BITS == 32);
11191dc4fe70SRichard Henderson             if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
11200b4286ddSRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0],
11210b4286ddSRichard Henderson                                  deposit64(arg_info(op->args[1])->val, 32, 32,
11220b4286ddSRichard Henderson                                            arg_info(op->args[2])->val));
11231dc4fe70SRichard Henderson                 break;
11241dc4fe70SRichard Henderson             } else if (args_are_copies(op->args[1], op->args[2])) {
11251dc4fe70SRichard Henderson                 op->opc = INDEX_op_dup_vec;
11261dc4fe70SRichard Henderson                 TCGOP_VECE(op) = MO_32;
11271dc4fe70SRichard Henderson                 nb_iargs = 1;
11281dc4fe70SRichard Henderson             }
11291dc4fe70SRichard Henderson             goto do_default;
11301dc4fe70SRichard Henderson 
1131a640f031SKirill Batuzov         CASE_OP_32_64(not):
1132cb25c80aSRichard Henderson         CASE_OP_32_64(neg):
113325c4d9ccSRichard Henderson         CASE_OP_32_64(ext8s):
113425c4d9ccSRichard Henderson         CASE_OP_32_64(ext8u):
113525c4d9ccSRichard Henderson         CASE_OP_32_64(ext16s):
113625c4d9ccSRichard Henderson         CASE_OP_32_64(ext16u):
1137a768e4e9SRichard Henderson         CASE_OP_32_64(ctpop):
11386498594cSRichard Henderson         CASE_OP_32_64(bswap16):
11396498594cSRichard Henderson         CASE_OP_32_64(bswap32):
11406498594cSRichard Henderson         case INDEX_op_bswap64_i64:
1141a640f031SKirill Batuzov         case INDEX_op_ext32s_i64:
1142a640f031SKirill Batuzov         case INDEX_op_ext32u_i64:
11438bcb5c8fSAurelien Jarno         case INDEX_op_ext_i32_i64:
11448bcb5c8fSAurelien Jarno         case INDEX_op_extu_i32_i64:
1145609ad705SRichard Henderson         case INDEX_op_extrl_i64_i32:
1146609ad705SRichard Henderson         case INDEX_op_extrh_i64_i32:
11476349039dSRichard Henderson             if (arg_is_const(op->args[1])) {
11486349039dSRichard Henderson                 tmp = do_constant_folding(opc, arg_info(op->args[1])->val, 0);
11498fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
1150a640f031SKirill Batuzov                 break;
11516e14e91bSRichard Henderson             }
11526e14e91bSRichard Henderson             goto do_default;
11536e14e91bSRichard Henderson 
115453108fb5SKirill Batuzov         CASE_OP_32_64(add):
115553108fb5SKirill Batuzov         CASE_OP_32_64(sub):
115653108fb5SKirill Batuzov         CASE_OP_32_64(mul):
11579a81090bSKirill Batuzov         CASE_OP_32_64(or):
11589a81090bSKirill Batuzov         CASE_OP_32_64(and):
11599a81090bSKirill Batuzov         CASE_OP_32_64(xor):
116055c0975cSKirill Batuzov         CASE_OP_32_64(shl):
116155c0975cSKirill Batuzov         CASE_OP_32_64(shr):
116255c0975cSKirill Batuzov         CASE_OP_32_64(sar):
116325c4d9ccSRichard Henderson         CASE_OP_32_64(rotl):
116425c4d9ccSRichard Henderson         CASE_OP_32_64(rotr):
1165cb25c80aSRichard Henderson         CASE_OP_32_64(andc):
1166cb25c80aSRichard Henderson         CASE_OP_32_64(orc):
1167cb25c80aSRichard Henderson         CASE_OP_32_64(eqv):
1168cb25c80aSRichard Henderson         CASE_OP_32_64(nand):
1169cb25c80aSRichard Henderson         CASE_OP_32_64(nor):
117003271524SRichard Henderson         CASE_OP_32_64(muluh):
117103271524SRichard Henderson         CASE_OP_32_64(mulsh):
117201547f7fSRichard Henderson         CASE_OP_32_64(div):
117301547f7fSRichard Henderson         CASE_OP_32_64(divu):
117401547f7fSRichard Henderson         CASE_OP_32_64(rem):
117501547f7fSRichard Henderson         CASE_OP_32_64(remu):
11766349039dSRichard Henderson             if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
11776349039dSRichard Henderson                 tmp = do_constant_folding(opc, arg_info(op->args[1])->val,
11786349039dSRichard Henderson                                           arg_info(op->args[2])->val);
11798fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
118053108fb5SKirill Batuzov                 break;
11816e14e91bSRichard Henderson             }
11826e14e91bSRichard Henderson             goto do_default;
11836e14e91bSRichard Henderson 
11840e28d006SRichard Henderson         CASE_OP_32_64(clz):
11850e28d006SRichard Henderson         CASE_OP_32_64(ctz):
11866349039dSRichard Henderson             if (arg_is_const(op->args[1])) {
11876349039dSRichard Henderson                 TCGArg v = arg_info(op->args[1])->val;
11880e28d006SRichard Henderson                 if (v != 0) {
11890e28d006SRichard Henderson                     tmp = do_constant_folding(opc, v, 0);
11908fe35e04SRichard Henderson                     tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
11910e28d006SRichard Henderson                 } else {
1192acd93701SRichard Henderson                     tcg_opt_gen_mov(s, op, op->args[0], op->args[2]);
11930e28d006SRichard Henderson                 }
11940e28d006SRichard Henderson                 break;
11950e28d006SRichard Henderson             }
11960e28d006SRichard Henderson             goto do_default;
11970e28d006SRichard Henderson 
11987ef55fc9SAurelien Jarno         CASE_OP_32_64(deposit):
11996349039dSRichard Henderson             if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
12006349039dSRichard Henderson                 tmp = deposit64(arg_info(op->args[1])->val,
12016349039dSRichard Henderson                                 op->args[3], op->args[4],
12026349039dSRichard Henderson                                 arg_info(op->args[2])->val);
12038fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
12047ef55fc9SAurelien Jarno                 break;
12056e14e91bSRichard Henderson             }
12066e14e91bSRichard Henderson             goto do_default;
12076e14e91bSRichard Henderson 
12087ec8bab3SRichard Henderson         CASE_OP_32_64(extract):
12096349039dSRichard Henderson             if (arg_is_const(op->args[1])) {
12106349039dSRichard Henderson                 tmp = extract64(arg_info(op->args[1])->val,
1211acd93701SRichard Henderson                                 op->args[2], op->args[3]);
12128fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
12137ec8bab3SRichard Henderson                 break;
12147ec8bab3SRichard Henderson             }
12157ec8bab3SRichard Henderson             goto do_default;
12167ec8bab3SRichard Henderson 
12177ec8bab3SRichard Henderson         CASE_OP_32_64(sextract):
12186349039dSRichard Henderson             if (arg_is_const(op->args[1])) {
12196349039dSRichard Henderson                 tmp = sextract64(arg_info(op->args[1])->val,
1220acd93701SRichard Henderson                                  op->args[2], op->args[3]);
12218fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
12227ec8bab3SRichard Henderson                 break;
12237ec8bab3SRichard Henderson             }
12247ec8bab3SRichard Henderson             goto do_default;
12257ec8bab3SRichard Henderson 
1226fce1296fSRichard Henderson         CASE_OP_32_64(extract2):
1227fce1296fSRichard Henderson             if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) {
122854795544SRichard Henderson                 uint64_t v1 = arg_info(op->args[1])->val;
122954795544SRichard Henderson                 uint64_t v2 = arg_info(op->args[2])->val;
123054795544SRichard Henderson                 int shr = op->args[3];
1231fce1296fSRichard Henderson 
1232fce1296fSRichard Henderson                 if (opc == INDEX_op_extract2_i64) {
123354795544SRichard Henderson                     tmp = (v1 >> shr) | (v2 << (64 - shr));
1234fce1296fSRichard Henderson                 } else {
123554795544SRichard Henderson                     tmp = (int32_t)(((uint32_t)v1 >> shr) |
123654795544SRichard Henderson                                     ((uint32_t)v2 << (32 - shr)));
1237fce1296fSRichard Henderson                 }
12388fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
1239fce1296fSRichard Henderson                 break;
1240fce1296fSRichard Henderson             }
1241fce1296fSRichard Henderson             goto do_default;
1242fce1296fSRichard Henderson 
1243f8dd19e5SAurelien Jarno         CASE_OP_32_64(setcond):
1244acd93701SRichard Henderson             tmp = do_constant_folding_cond(opc, op->args[1],
1245acd93701SRichard Henderson                                            op->args[2], op->args[3]);
1246b336ceb6SAurelien Jarno             if (tmp != 2) {
12478fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
1248f8dd19e5SAurelien Jarno                 break;
12496e14e91bSRichard Henderson             }
12506e14e91bSRichard Henderson             goto do_default;
12516e14e91bSRichard Henderson 
1252fbeaa26cSAurelien Jarno         CASE_OP_32_64(brcond):
1253acd93701SRichard Henderson             tmp = do_constant_folding_cond(opc, op->args[0],
1254acd93701SRichard Henderson                                            op->args[1], op->args[2]);
1255b336ceb6SAurelien Jarno             if (tmp != 2) {
1256b336ceb6SAurelien Jarno                 if (tmp) {
12578fe35e04SRichard Henderson                     memset(&temps_used, 0, sizeof(temps_used));
1258c45cb8bbSRichard Henderson                     op->opc = INDEX_op_br;
1259acd93701SRichard Henderson                     op->args[0] = op->args[3];
1260fbeaa26cSAurelien Jarno                 } else {
12610c627cdcSRichard Henderson                     tcg_op_remove(s, op);
1262fbeaa26cSAurelien Jarno                 }
1263fbeaa26cSAurelien Jarno                 break;
12646e14e91bSRichard Henderson             }
12656e14e91bSRichard Henderson             goto do_default;
12666e14e91bSRichard Henderson 
1267fa01a208SRichard Henderson         CASE_OP_32_64(movcond):
1268acd93701SRichard Henderson             tmp = do_constant_folding_cond(opc, op->args[1],
1269acd93701SRichard Henderson                                            op->args[2], op->args[5]);
1270b336ceb6SAurelien Jarno             if (tmp != 2) {
1271acd93701SRichard Henderson                 tcg_opt_gen_mov(s, op, op->args[0], op->args[4-tmp]);
1272fa01a208SRichard Henderson                 break;
12736e14e91bSRichard Henderson             }
12746349039dSRichard Henderson             if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) {
127554795544SRichard Henderson                 uint64_t tv = arg_info(op->args[3])->val;
127654795544SRichard Henderson                 uint64_t fv = arg_info(op->args[4])->val;
1277acd93701SRichard Henderson                 TCGCond cond = op->args[5];
127854795544SRichard Henderson 
1279333b21b8SRichard Henderson                 if (fv == 1 && tv == 0) {
1280333b21b8SRichard Henderson                     cond = tcg_invert_cond(cond);
1281333b21b8SRichard Henderson                 } else if (!(tv == 1 && fv == 0)) {
1282333b21b8SRichard Henderson                     goto do_default;
1283333b21b8SRichard Henderson                 }
1284acd93701SRichard Henderson                 op->args[3] = cond;
1285333b21b8SRichard Henderson                 op->opc = opc = (opc == INDEX_op_movcond_i32
1286333b21b8SRichard Henderson                                  ? INDEX_op_setcond_i32
1287333b21b8SRichard Henderson                                  : INDEX_op_setcond_i64);
1288333b21b8SRichard Henderson                 nb_iargs = 2;
1289333b21b8SRichard Henderson             }
12906e14e91bSRichard Henderson             goto do_default;
12916e14e91bSRichard Henderson 
1292212c328dSRichard Henderson         case INDEX_op_add2_i32:
1293212c328dSRichard Henderson         case INDEX_op_sub2_i32:
12946349039dSRichard Henderson             if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])
12956349039dSRichard Henderson                 && arg_is_const(op->args[4]) && arg_is_const(op->args[5])) {
12966349039dSRichard Henderson                 uint32_t al = arg_info(op->args[2])->val;
12976349039dSRichard Henderson                 uint32_t ah = arg_info(op->args[3])->val;
12986349039dSRichard Henderson                 uint32_t bl = arg_info(op->args[4])->val;
12996349039dSRichard Henderson                 uint32_t bh = arg_info(op->args[5])->val;
1300212c328dSRichard Henderson                 uint64_t a = ((uint64_t)ah << 32) | al;
1301212c328dSRichard Henderson                 uint64_t b = ((uint64_t)bh << 32) | bl;
1302212c328dSRichard Henderson                 TCGArg rl, rh;
13038fe35e04SRichard Henderson                 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_mov_i32);
1304212c328dSRichard Henderson 
1305c45cb8bbSRichard Henderson                 if (opc == INDEX_op_add2_i32) {
1306212c328dSRichard Henderson                     a += b;
1307212c328dSRichard Henderson                 } else {
1308212c328dSRichard Henderson                     a -= b;
1309212c328dSRichard Henderson                 }
1310212c328dSRichard Henderson 
1311acd93701SRichard Henderson                 rl = op->args[0];
1312acd93701SRichard Henderson                 rh = op->args[1];
13138fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, rl, (int32_t)a);
13148fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op2, rh, (int32_t)(a >> 32));
1315212c328dSRichard Henderson                 break;
1316212c328dSRichard Henderson             }
1317212c328dSRichard Henderson             goto do_default;
1318212c328dSRichard Henderson 
13191414968aSRichard Henderson         case INDEX_op_mulu2_i32:
13206349039dSRichard Henderson             if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) {
13216349039dSRichard Henderson                 uint32_t a = arg_info(op->args[2])->val;
13226349039dSRichard Henderson                 uint32_t b = arg_info(op->args[3])->val;
13231414968aSRichard Henderson                 uint64_t r = (uint64_t)a * b;
13241414968aSRichard Henderson                 TCGArg rl, rh;
13258fe35e04SRichard Henderson                 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_mov_i32);
13261414968aSRichard Henderson 
1327acd93701SRichard Henderson                 rl = op->args[0];
1328acd93701SRichard Henderson                 rh = op->args[1];
13298fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, rl, (int32_t)r);
13308fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op2, rh, (int32_t)(r >> 32));
13311414968aSRichard Henderson                 break;
13321414968aSRichard Henderson             }
13331414968aSRichard Henderson             goto do_default;
13341414968aSRichard Henderson 
1335bc1473efSRichard Henderson         case INDEX_op_brcond2_i32:
1336acd93701SRichard Henderson             tmp = do_constant_folding_cond2(&op->args[0], &op->args[2],
1337acd93701SRichard Henderson                                             op->args[4]);
13386c4382f8SRichard Henderson             if (tmp != 2) {
13396c4382f8SRichard Henderson                 if (tmp) {
1340a763551aSRichard Henderson             do_brcond_true:
13418fe35e04SRichard Henderson                     memset(&temps_used, 0, sizeof(temps_used));
1342c45cb8bbSRichard Henderson                     op->opc = INDEX_op_br;
1343acd93701SRichard Henderson                     op->args[0] = op->args[5];
13446c4382f8SRichard Henderson                 } else {
1345a763551aSRichard Henderson             do_brcond_false:
13460c627cdcSRichard Henderson                     tcg_op_remove(s, op);
13476c4382f8SRichard Henderson                 }
1348acd93701SRichard Henderson             } else if ((op->args[4] == TCG_COND_LT
1349acd93701SRichard Henderson                         || op->args[4] == TCG_COND_GE)
13506349039dSRichard Henderson                        && arg_is_const(op->args[2])
13516349039dSRichard Henderson                        && arg_info(op->args[2])->val == 0
13526349039dSRichard Henderson                        && arg_is_const(op->args[3])
13536349039dSRichard Henderson                        && arg_info(op->args[3])->val == 0) {
13546c4382f8SRichard Henderson                 /* Simplify LT/GE comparisons vs zero to a single compare
13556c4382f8SRichard Henderson                    vs the high word of the input.  */
1356a763551aSRichard Henderson             do_brcond_high:
13578fe35e04SRichard Henderson                 memset(&temps_used, 0, sizeof(temps_used));
1358c45cb8bbSRichard Henderson                 op->opc = INDEX_op_brcond_i32;
1359acd93701SRichard Henderson                 op->args[0] = op->args[1];
1360acd93701SRichard Henderson                 op->args[1] = op->args[3];
1361acd93701SRichard Henderson                 op->args[2] = op->args[4];
1362acd93701SRichard Henderson                 op->args[3] = op->args[5];
1363acd93701SRichard Henderson             } else if (op->args[4] == TCG_COND_EQ) {
1364a763551aSRichard Henderson                 /* Simplify EQ comparisons where one of the pairs
1365a763551aSRichard Henderson                    can be simplified.  */
1366a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1367acd93701SRichard Henderson                                                op->args[0], op->args[2],
1368acd93701SRichard Henderson                                                TCG_COND_EQ);
1369a763551aSRichard Henderson                 if (tmp == 0) {
1370a763551aSRichard Henderson                     goto do_brcond_false;
1371a763551aSRichard Henderson                 } else if (tmp == 1) {
1372a763551aSRichard Henderson                     goto do_brcond_high;
1373a763551aSRichard Henderson                 }
1374a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1375acd93701SRichard Henderson                                                op->args[1], op->args[3],
1376acd93701SRichard Henderson                                                TCG_COND_EQ);
1377a763551aSRichard Henderson                 if (tmp == 0) {
1378a763551aSRichard Henderson                     goto do_brcond_false;
1379a763551aSRichard Henderson                 } else if (tmp != 1) {
1380a763551aSRichard Henderson                     goto do_default;
1381a763551aSRichard Henderson                 }
1382a763551aSRichard Henderson             do_brcond_low:
13838fe35e04SRichard Henderson                 memset(&temps_used, 0, sizeof(temps_used));
1384c45cb8bbSRichard Henderson                 op->opc = INDEX_op_brcond_i32;
1385acd93701SRichard Henderson                 op->args[1] = op->args[2];
1386acd93701SRichard Henderson                 op->args[2] = op->args[4];
1387acd93701SRichard Henderson                 op->args[3] = op->args[5];
1388acd93701SRichard Henderson             } else if (op->args[4] == TCG_COND_NE) {
1389a763551aSRichard Henderson                 /* Simplify NE comparisons where one of the pairs
1390a763551aSRichard Henderson                    can be simplified.  */
1391a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1392acd93701SRichard Henderson                                                op->args[0], op->args[2],
1393acd93701SRichard Henderson                                                TCG_COND_NE);
1394a763551aSRichard Henderson                 if (tmp == 0) {
1395a763551aSRichard Henderson                     goto do_brcond_high;
1396a763551aSRichard Henderson                 } else if (tmp == 1) {
1397a763551aSRichard Henderson                     goto do_brcond_true;
1398a763551aSRichard Henderson                 }
1399a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
1400acd93701SRichard Henderson                                                op->args[1], op->args[3],
1401acd93701SRichard Henderson                                                TCG_COND_NE);
1402a763551aSRichard Henderson                 if (tmp == 0) {
1403a763551aSRichard Henderson                     goto do_brcond_low;
1404a763551aSRichard Henderson                 } else if (tmp == 1) {
1405a763551aSRichard Henderson                     goto do_brcond_true;
1406a763551aSRichard Henderson                 }
1407a763551aSRichard Henderson                 goto do_default;
14086c4382f8SRichard Henderson             } else {
1409bc1473efSRichard Henderson                 goto do_default;
14106c4382f8SRichard Henderson             }
14116c4382f8SRichard Henderson             break;
1412bc1473efSRichard Henderson 
1413bc1473efSRichard Henderson         case INDEX_op_setcond2_i32:
1414acd93701SRichard Henderson             tmp = do_constant_folding_cond2(&op->args[1], &op->args[3],
1415acd93701SRichard Henderson                                             op->args[5]);
14166c4382f8SRichard Henderson             if (tmp != 2) {
1417a763551aSRichard Henderson             do_setcond_const:
14188fe35e04SRichard Henderson                 tcg_opt_gen_movi(s, &temps_used, op, op->args[0], tmp);
1419acd93701SRichard Henderson             } else if ((op->args[5] == TCG_COND_LT
1420acd93701SRichard Henderson                         || op->args[5] == TCG_COND_GE)
14216349039dSRichard Henderson                        && arg_is_const(op->args[3])
14226349039dSRichard Henderson                        && arg_info(op->args[3])->val == 0
14236349039dSRichard Henderson                        && arg_is_const(op->args[4])
14246349039dSRichard Henderson                        && arg_info(op->args[4])->val == 0) {
14256c4382f8SRichard Henderson                 /* Simplify LT/GE comparisons vs zero to a single compare
14266c4382f8SRichard Henderson                    vs the high word of the input.  */
1427a763551aSRichard Henderson             do_setcond_high:
1428acd93701SRichard Henderson                 reset_temp(op->args[0]);
14296349039dSRichard Henderson                 arg_info(op->args[0])->mask = 1;
1430c45cb8bbSRichard Henderson                 op->opc = INDEX_op_setcond_i32;
1431acd93701SRichard Henderson                 op->args[1] = op->args[2];
1432acd93701SRichard Henderson                 op->args[2] = op->args[4];
1433acd93701SRichard Henderson                 op->args[3] = op->args[5];
1434acd93701SRichard Henderson             } else if (op->args[5] == TCG_COND_EQ) {
1435a763551aSRichard Henderson                 /* Simplify EQ comparisons where one of the pairs
1436a763551aSRichard Henderson                    can be simplified.  */
1437a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1438acd93701SRichard Henderson                                                op->args[1], op->args[3],
1439acd93701SRichard Henderson                                                TCG_COND_EQ);
1440a763551aSRichard Henderson                 if (tmp == 0) {
1441a763551aSRichard Henderson                     goto do_setcond_const;
1442a763551aSRichard Henderson                 } else if (tmp == 1) {
1443a763551aSRichard Henderson                     goto do_setcond_high;
1444a763551aSRichard Henderson                 }
1445a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1446acd93701SRichard Henderson                                                op->args[2], op->args[4],
1447acd93701SRichard Henderson                                                TCG_COND_EQ);
1448a763551aSRichard Henderson                 if (tmp == 0) {
1449a763551aSRichard Henderson                     goto do_setcond_high;
1450a763551aSRichard Henderson                 } else if (tmp != 1) {
1451a763551aSRichard Henderson                     goto do_default;
1452a763551aSRichard Henderson                 }
1453a763551aSRichard Henderson             do_setcond_low:
1454acd93701SRichard Henderson                 reset_temp(op->args[0]);
14556349039dSRichard Henderson                 arg_info(op->args[0])->mask = 1;
1456c45cb8bbSRichard Henderson                 op->opc = INDEX_op_setcond_i32;
1457acd93701SRichard Henderson                 op->args[2] = op->args[3];
1458acd93701SRichard Henderson                 op->args[3] = op->args[5];
1459acd93701SRichard Henderson             } else if (op->args[5] == TCG_COND_NE) {
1460a763551aSRichard Henderson                 /* Simplify NE comparisons where one of the pairs
1461a763551aSRichard Henderson                    can be simplified.  */
1462a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1463acd93701SRichard Henderson                                                op->args[1], op->args[3],
1464acd93701SRichard Henderson                                                TCG_COND_NE);
1465a763551aSRichard Henderson                 if (tmp == 0) {
1466a763551aSRichard Henderson                     goto do_setcond_high;
1467a763551aSRichard Henderson                 } else if (tmp == 1) {
1468a763551aSRichard Henderson                     goto do_setcond_const;
1469a763551aSRichard Henderson                 }
1470a763551aSRichard Henderson                 tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
1471acd93701SRichard Henderson                                                op->args[2], op->args[4],
1472acd93701SRichard Henderson                                                TCG_COND_NE);
1473a763551aSRichard Henderson                 if (tmp == 0) {
1474a763551aSRichard Henderson                     goto do_setcond_low;
1475a763551aSRichard Henderson                 } else if (tmp == 1) {
1476a763551aSRichard Henderson                     goto do_setcond_const;
1477a763551aSRichard Henderson                 }
1478a763551aSRichard Henderson                 goto do_default;
14796c4382f8SRichard Henderson             } else {
14806c4382f8SRichard Henderson                 goto do_default;
14816c4382f8SRichard Henderson             }
1482bc1473efSRichard Henderson             break;
1483bc1473efSRichard Henderson 
14848f2e8c07SKirill Batuzov         case INDEX_op_call:
1485*90163900SRichard Henderson             if (!(tcg_call_flags(op)
1486cf066674SRichard Henderson                   & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
148722613af4SKirill Batuzov                 for (i = 0; i < nb_globals; i++) {
14881208d7ddSAurelien Jarno                     if (test_bit(i, temps_used.l)) {
14896349039dSRichard Henderson                         reset_ts(&s->temps[i]);
149022613af4SKirill Batuzov                     }
149122613af4SKirill Batuzov                 }
14921208d7ddSAurelien Jarno             }
1493c56caea3SRichard Henderson             goto do_reset_output;
14946e14e91bSRichard Henderson 
14958f2e8c07SKirill Batuzov         default:
14966e14e91bSRichard Henderson         do_default:
1497c56caea3SRichard Henderson             /* Default case: we know nothing about operation (or were unable
1498c56caea3SRichard Henderson                to compute the operation result) so no propagation is done.
1499c56caea3SRichard Henderson                We trash everything if the operation is the end of a basic
1500c56caea3SRichard Henderson                block, otherwise we only trash the output args.  "mask" is
1501c56caea3SRichard Henderson                the non-zero bits mask for the first output arg.  */
1502c56caea3SRichard Henderson             if (def->flags & TCG_OPF_BB_END) {
15038fe35e04SRichard Henderson                 memset(&temps_used, 0, sizeof(temps_used));
1504c56caea3SRichard Henderson             } else {
1505c56caea3SRichard Henderson         do_reset_output:
1506cf066674SRichard Henderson                 for (i = 0; i < nb_oargs; i++) {
1507acd93701SRichard Henderson                     reset_temp(op->args[i]);
1508c56caea3SRichard Henderson                     /* Save the corresponding known-zero bits mask for the
1509c56caea3SRichard Henderson                        first output argument (only one supported so far). */
15103031244bSAurelien Jarno                     if (i == 0) {
15116349039dSRichard Henderson                         arg_info(op->args[i])->mask = mask;
15123031244bSAurelien Jarno                     }
151322613af4SKirill Batuzov                 }
1514c56caea3SRichard Henderson             }
15158f2e8c07SKirill Batuzov             break;
15168f2e8c07SKirill Batuzov         }
151734f93921SPranith Kumar 
151834f93921SPranith Kumar         /* Eliminate duplicate and redundant fence instructions.  */
1519acd93701SRichard Henderson         if (prev_mb) {
152034f93921SPranith Kumar             switch (opc) {
152134f93921SPranith Kumar             case INDEX_op_mb:
152234f93921SPranith Kumar                 /* Merge two barriers of the same type into one,
152334f93921SPranith Kumar                  * or a weaker barrier into a stronger one,
152434f93921SPranith Kumar                  * or two weaker barriers into a stronger one.
152534f93921SPranith Kumar                  *   mb X; mb Y => mb X|Y
152634f93921SPranith Kumar                  *   mb; strl => mb; st
152734f93921SPranith Kumar                  *   ldaq; mb => ld; mb
152834f93921SPranith Kumar                  *   ldaq; strl => ld; mb; st
152934f93921SPranith Kumar                  * Other combinations are also merged into a strong
153034f93921SPranith Kumar                  * barrier.  This is stricter than specified but for
153134f93921SPranith Kumar                  * the purposes of TCG is better than not optimizing.
153234f93921SPranith Kumar                  */
1533acd93701SRichard Henderson                 prev_mb->args[0] |= op->args[0];
153434f93921SPranith Kumar                 tcg_op_remove(s, op);
153534f93921SPranith Kumar                 break;
153634f93921SPranith Kumar 
153734f93921SPranith Kumar             default:
153834f93921SPranith Kumar                 /* Opcodes that end the block stop the optimization.  */
153934f93921SPranith Kumar                 if ((def->flags & TCG_OPF_BB_END) == 0) {
154034f93921SPranith Kumar                     break;
154134f93921SPranith Kumar                 }
154234f93921SPranith Kumar                 /* fallthru */
154334f93921SPranith Kumar             case INDEX_op_qemu_ld_i32:
154434f93921SPranith Kumar             case INDEX_op_qemu_ld_i64:
154534f93921SPranith Kumar             case INDEX_op_qemu_st_i32:
154607ce0b05SRichard Henderson             case INDEX_op_qemu_st8_i32:
154734f93921SPranith Kumar             case INDEX_op_qemu_st_i64:
154834f93921SPranith Kumar             case INDEX_op_call:
154934f93921SPranith Kumar                 /* Opcodes that touch guest memory stop the optimization.  */
1550acd93701SRichard Henderson                 prev_mb = NULL;
155134f93921SPranith Kumar                 break;
155234f93921SPranith Kumar             }
155334f93921SPranith Kumar         } else if (opc == INDEX_op_mb) {
1554acd93701SRichard Henderson             prev_mb = op;
155534f93921SPranith Kumar         }
15568f2e8c07SKirill Batuzov     }
15578f2e8c07SKirill Batuzov }
1558