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