optimize.c 40.1 KB
Newer Older
K
Kirill Batuzov 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
/*
 * Optimizations for Tiny Code Generator for QEMU
 *
 * Copyright (c) 2010 Samsung Electronics.
 * Contributed by Kirill Batuzov <batuzovk@ispras.ru>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

P
Peter Maydell 已提交
26
#include "qemu/osdep.h"
K
Kirill Batuzov 已提交
27
#include "qemu-common.h"
28
#include "cpu.h"
K
Kirill Batuzov 已提交
29 30 31 32 33 34
#include "tcg-op.h"

#define CASE_OP_32_64(x)                        \
        glue(glue(case INDEX_op_, x), _i32):    \
        glue(glue(case INDEX_op_, x), _i64)

35
struct tcg_temp_info {
36
    bool is_const;
37 38 39
    uint16_t prev_copy;
    uint16_t next_copy;
    tcg_target_ulong val;
40
    tcg_target_ulong mask;
41 42 43
};

static struct tcg_temp_info temps[TCG_MAX_TEMPS];
44
static TCGTempSet temps_used;
45

46 47
static inline bool temp_is_const(TCGArg arg)
{
48
    return temps[arg].is_const;
49 50 51 52
}

static inline bool temp_is_copy(TCGArg arg)
{
53
    return temps[arg].next_copy != arg;
54 55
}

56
/* Reset TEMP's state, possibly removing the temp for the list of copies.  */
57
static void reset_temp(TCGArg temp)
58
{
59 60 61 62 63
    temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy;
    temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy;
    temps[temp].next_copy = temp;
    temps[temp].prev_copy = temp;
    temps[temp].is_const = false;
64
    temps[temp].mask = -1;
65 66
}

67 68 69 70 71 72 73 74 75 76
/* Reset all temporaries, given that there are NB_TEMPS of them.  */
static void reset_all_temps(int nb_temps)
{
    bitmap_zero(temps_used.l, nb_temps);
}

/* Initialize and activate a temporary.  */
static void init_temp_info(TCGArg temp)
{
    if (!test_bit(temp, temps_used.l)) {
77 78 79
        temps[temp].next_copy = temp;
        temps[temp].prev_copy = temp;
        temps[temp].is_const = false;
80 81 82 83 84
        temps[temp].mask = -1;
        set_bit(temp, temps_used.l);
    }
}

85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
static TCGOp *insert_op_before(TCGContext *s, TCGOp *old_op,
                                TCGOpcode opc, int nargs)
{
    int oi = s->gen_next_op_idx;
    int pi = s->gen_next_parm_idx;
    int prev = old_op->prev;
    int next = old_op - s->gen_op_buf;
    TCGOp *new_op;

    tcg_debug_assert(oi < OPC_BUF_SIZE);
    tcg_debug_assert(pi + nargs <= OPPARAM_BUF_SIZE);
    s->gen_next_op_idx = oi + 1;
    s->gen_next_parm_idx = pi + nargs;

    new_op = &s->gen_op_buf[oi];
    *new_op = (TCGOp){
        .opc = opc,
        .args = pi,
        .prev = prev,
        .next = next
    };
    if (prev >= 0) {
        s->gen_op_buf[prev].next = oi;
    } else {
        s->gen_first_op_idx = oi;
    }
    old_op->prev = oi;

    return new_op;
}

B
Blue Swirl 已提交
116
static int op_bits(TCGOpcode op)
117
{
118 119
    const TCGOpDef *def = &tcg_op_defs[op];
    return def->flags & TCG_OPF_64BIT ? 64 : 32;
120 121
}

122 123 124 125 126 127 128 129 130 131 132 133 134 135
static TCGOpcode op_to_mov(TCGOpcode op)
{
    switch (op_bits(op)) {
    case 32:
        return INDEX_op_mov_i32;
    case 64:
        return INDEX_op_mov_i64;
    default:
        fprintf(stderr, "op_to_mov: unexpected return value of "
                "function op_bits.\n");
        tcg_abort();
    }
}

B
Blue Swirl 已提交
136
static TCGOpcode op_to_movi(TCGOpcode op)
137 138 139 140 141 142 143 144 145 146 147 148 149
{
    switch (op_bits(op)) {
    case 32:
        return INDEX_op_movi_i32;
    case 64:
        return INDEX_op_movi_i64;
    default:
        fprintf(stderr, "op_to_movi: unexpected return value of "
                "function op_bits.\n");
        tcg_abort();
    }
}

150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186
static TCGArg find_better_copy(TCGContext *s, TCGArg temp)
{
    TCGArg i;

    /* If this is already a global, we can't do better. */
    if (temp < s->nb_globals) {
        return temp;
    }

    /* Search for a global first. */
    for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
        if (i < s->nb_globals) {
            return i;
        }
    }

    /* If it is a temp, search for a temp local. */
    if (!s->temps[temp].temp_local) {
        for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) {
            if (s->temps[i].temp_local) {
                return i;
            }
        }
    }

    /* Failure to find a better representation, return the same temp. */
    return temp;
}

static bool temps_are_copies(TCGArg arg1, TCGArg arg2)
{
    TCGArg i;

    if (arg1 == arg2) {
        return true;
    }

187
    if (!temp_is_copy(arg1) || !temp_is_copy(arg2)) {
188 189 190 191 192 193 194 195 196 197 198 199
        return false;
    }

    for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) {
        if (i == arg2) {
            return true;
        }
    }

    return false;
}

200 201 202 203 204 205 206 207 208
static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg *args,
                             TCGArg dst, TCGArg val)
{
    TCGOpcode new_op = op_to_movi(op->opc);
    tcg_target_ulong mask;

    op->opc = new_op;

    reset_temp(dst);
209
    temps[dst].is_const = true;
210 211
    temps[dst].val = val;
    mask = val;
212
    if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) {
213 214 215 216 217 218 219 220 221
        /* High bits of the destination are now garbage.  */
        mask |= ~0xffffffffull;
    }
    temps[dst].mask = mask;

    args[0] = dst;
    args[1] = val;
}

222
static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg *args,
223
                            TCGArg dst, TCGArg src)
224
{
225 226 227 228 229
    if (temps_are_copies(dst, src)) {
        tcg_op_remove(s, op);
        return;
    }

230
    TCGOpcode new_op = op_to_mov(op->opc);
231
    tcg_target_ulong mask;
232

233
    op->opc = new_op;
234

235
    reset_temp(dst);
236 237 238 239 240 241 242
    mask = temps[src].mask;
    if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) {
        /* High bits of the destination are now garbage.  */
        mask |= ~0xffffffffull;
    }
    temps[dst].mask = mask;

243 244 245 246 247
    if (s->temps[src].type == s->temps[dst].type) {
        temps[dst].next_copy = temps[src].next_copy;
        temps[dst].prev_copy = src;
        temps[temps[dst].next_copy].prev_copy = dst;
        temps[src].next_copy = dst;
248 249
        temps[dst].is_const = temps[src].is_const;
        temps[dst].val = temps[src].val;
250
    }
251

252 253
    args[0] = dst;
    args[1] = src;
254 255
}

B
Blue Swirl 已提交
256
static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y)
257
{
258 259
    uint64_t l64, h64;

260 261 262 263 264 265 266 267 268 269
    switch (op) {
    CASE_OP_32_64(add):
        return x + y;

    CASE_OP_32_64(sub):
        return x - y;

    CASE_OP_32_64(mul):
        return x * y;

270 271 272 273 274 275 276 277 278
    CASE_OP_32_64(and):
        return x & y;

    CASE_OP_32_64(or):
        return x | y;

    CASE_OP_32_64(xor):
        return x ^ y;

279
    case INDEX_op_shl_i32:
280
        return (uint32_t)x << (y & 31);
281 282

    case INDEX_op_shl_i64:
283
        return (uint64_t)x << (y & 63);
284 285

    case INDEX_op_shr_i32:
286
        return (uint32_t)x >> (y & 31);
287 288

    case INDEX_op_shr_i64:
289
        return (uint64_t)x >> (y & 63);
290 291

    case INDEX_op_sar_i32:
292
        return (int32_t)x >> (y & 31);
293 294

    case INDEX_op_sar_i64:
295
        return (int64_t)x >> (y & 63);
296 297

    case INDEX_op_rotr_i32:
298
        return ror32(x, y & 31);
299 300

    case INDEX_op_rotr_i64:
301
        return ror64(x, y & 63);
302 303

    case INDEX_op_rotl_i32:
304
        return rol32(x, y & 31);
305 306

    case INDEX_op_rotl_i64:
307
        return rol64(x, y & 63);
308 309

    CASE_OP_32_64(not):
310
        return ~x;
311

312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
    CASE_OP_32_64(neg):
        return -x;

    CASE_OP_32_64(andc):
        return x & ~y;

    CASE_OP_32_64(orc):
        return x | ~y;

    CASE_OP_32_64(eqv):
        return ~(x ^ y);

    CASE_OP_32_64(nand):
        return ~(x & y);

    CASE_OP_32_64(nor):
        return ~(x | y);

330
    CASE_OP_32_64(ext8s):
331
        return (int8_t)x;
332 333

    CASE_OP_32_64(ext16s):
334
        return (int16_t)x;
335 336

    CASE_OP_32_64(ext8u):
337
        return (uint8_t)x;
338 339

    CASE_OP_32_64(ext16u):
340 341
        return (uint16_t)x;

342
    case INDEX_op_ext_i32_i64:
343 344 345
    case INDEX_op_ext32s_i64:
        return (int32_t)x;

346
    case INDEX_op_extu_i32_i64:
347
    case INDEX_op_extrl_i64_i32:
348 349 350
    case INDEX_op_ext32u_i64:
        return (uint32_t)x;

351 352 353
    case INDEX_op_extrh_i64_i32:
        return (uint64_t)x >> 32;

354 355 356 357 358 359 360 361 362 363 364 365
    case INDEX_op_muluh_i32:
        return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32;
    case INDEX_op_mulsh_i32:
        return ((int64_t)(int32_t)x * (int32_t)y) >> 32;

    case INDEX_op_muluh_i64:
        mulu64(&l64, &h64, x, y);
        return h64;
    case INDEX_op_mulsh_i64:
        muls64(&l64, &h64, x, y);
        return h64;

R
Richard Henderson 已提交
366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
    case INDEX_op_div_i32:
        /* Avoid crashing on divide by zero, otherwise undefined.  */
        return (int32_t)x / ((int32_t)y ? : 1);
    case INDEX_op_divu_i32:
        return (uint32_t)x / ((uint32_t)y ? : 1);
    case INDEX_op_div_i64:
        return (int64_t)x / ((int64_t)y ? : 1);
    case INDEX_op_divu_i64:
        return (uint64_t)x / ((uint64_t)y ? : 1);

    case INDEX_op_rem_i32:
        return (int32_t)x % ((int32_t)y ? : 1);
    case INDEX_op_remu_i32:
        return (uint32_t)x % ((uint32_t)y ? : 1);
    case INDEX_op_rem_i64:
        return (int64_t)x % ((int64_t)y ? : 1);
    case INDEX_op_remu_i64:
        return (uint64_t)x % ((uint64_t)y ? : 1);

385 386 387 388 389 390 391
    default:
        fprintf(stderr,
                "Unrecognized operation %d in do_constant_folding.\n", op);
        tcg_abort();
    }
}

B
Blue Swirl 已提交
392
static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y)
393 394 395
{
    TCGArg res = do_constant_folding_2(op, x, y);
    if (op_bits(op) == 32) {
396
        res = (int32_t)res;
397 398 399 400
    }
    return res;
}

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476
static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c)
{
    switch (c) {
    case TCG_COND_EQ:
        return x == y;
    case TCG_COND_NE:
        return x != y;
    case TCG_COND_LT:
        return (int32_t)x < (int32_t)y;
    case TCG_COND_GE:
        return (int32_t)x >= (int32_t)y;
    case TCG_COND_LE:
        return (int32_t)x <= (int32_t)y;
    case TCG_COND_GT:
        return (int32_t)x > (int32_t)y;
    case TCG_COND_LTU:
        return x < y;
    case TCG_COND_GEU:
        return x >= y;
    case TCG_COND_LEU:
        return x <= y;
    case TCG_COND_GTU:
        return x > y;
    default:
        tcg_abort();
    }
}

static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c)
{
    switch (c) {
    case TCG_COND_EQ:
        return x == y;
    case TCG_COND_NE:
        return x != y;
    case TCG_COND_LT:
        return (int64_t)x < (int64_t)y;
    case TCG_COND_GE:
        return (int64_t)x >= (int64_t)y;
    case TCG_COND_LE:
        return (int64_t)x <= (int64_t)y;
    case TCG_COND_GT:
        return (int64_t)x > (int64_t)y;
    case TCG_COND_LTU:
        return x < y;
    case TCG_COND_GEU:
        return x >= y;
    case TCG_COND_LEU:
        return x <= y;
    case TCG_COND_GTU:
        return x > y;
    default:
        tcg_abort();
    }
}

static bool do_constant_folding_cond_eq(TCGCond c)
{
    switch (c) {
    case TCG_COND_GT:
    case TCG_COND_LTU:
    case TCG_COND_LT:
    case TCG_COND_GTU:
    case TCG_COND_NE:
        return 0;
    case TCG_COND_GE:
    case TCG_COND_GEU:
    case TCG_COND_LE:
    case TCG_COND_LEU:
    case TCG_COND_EQ:
        return 1;
    default:
        tcg_abort();
    }
}

477 478
/* Return 2 if the condition can't be simplified, and the result
   of the condition (0 or 1) if it can */
479 480 481
static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x,
                                       TCGArg y, TCGCond c)
{
482
    if (temp_is_const(x) && temp_is_const(y)) {
483 484
        switch (op_bits(op)) {
        case 32:
485
            return do_constant_folding_cond_32(temps[x].val, temps[y].val, c);
486
        case 64:
487
            return do_constant_folding_cond_64(temps[x].val, temps[y].val, c);
488
        default:
489
            tcg_abort();
490
        }
491 492
    } else if (temps_are_copies(x, y)) {
        return do_constant_folding_cond_eq(c);
493
    } else if (temp_is_const(y) && temps[y].val == 0) {
494
        switch (c) {
495
        case TCG_COND_LTU:
496
            return 0;
497
        case TCG_COND_GEU:
498 499 500
            return 1;
        default:
            return 2;
501
        }
502 503
    } else {
        return 2;
504 505 506
    }
}

507 508 509 510 511 512 513
/* Return 2 if the condition can't be simplified, and the result
   of the condition (0 or 1) if it can */
static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c)
{
    TCGArg al = p1[0], ah = p1[1];
    TCGArg bl = p2[0], bh = p2[1];

514
    if (temp_is_const(bl) && temp_is_const(bh)) {
515 516
        uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val;

517
        if (temp_is_const(al) && temp_is_const(ah)) {
518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538
            uint64_t a;
            a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val;
            return do_constant_folding_cond_64(a, b, c);
        }
        if (b == 0) {
            switch (c) {
            case TCG_COND_LTU:
                return 0;
            case TCG_COND_GEU:
                return 1;
            default:
                break;
            }
        }
    }
    if (temps_are_copies(al, bl) && temps_are_copies(ah, bh)) {
        return do_constant_folding_cond_eq(c);
    }
    return 2;
}

539 540 541 542
static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2)
{
    TCGArg a1 = *p1, a2 = *p2;
    int sum = 0;
543 544
    sum += temp_is_const(a1);
    sum -= temp_is_const(a2);
545 546 547 548 549 550 551 552 553 554 555

    /* Prefer the constant in second argument, and then the form
       op a, a, b, which is better handled on non-RISC hosts. */
    if (sum > 0 || (sum == 0 && dest == a2)) {
        *p1 = a2;
        *p2 = a1;
        return true;
    }
    return false;
}

556 557 558
static bool swap_commutative2(TCGArg *p1, TCGArg *p2)
{
    int sum = 0;
559 560 561 562
    sum += temp_is_const(p1[0]);
    sum += temp_is_const(p1[1]);
    sum -= temp_is_const(p2[0]);
    sum -= temp_is_const(p2[1]);
563 564 565 566 567 568 569 570 571
    if (sum > 0) {
        TCGArg t;
        t = p1[0], p1[0] = p2[0], p2[0] = t;
        t = p1[1], p1[1] = p2[1], p2[1] = t;
        return true;
    }
    return false;
}

572
/* Propagate constants and copies, fold constant expressions. */
573
void tcg_optimize(TCGContext *s)
K
Kirill Batuzov 已提交
574
{
575
    int oi, oi_next, nb_temps, nb_globals;
576

577 578
    /* Array VALS has an element for each temp.
       If this temp holds a constant then its value is kept in VALS' element.
579 580
       If this temp is a copy of other ones then the other copies are
       available through the doubly linked circular list. */
K
Kirill Batuzov 已提交
581 582 583

    nb_temps = s->nb_temps;
    nb_globals = s->nb_globals;
584
    reset_all_temps(nb_temps);
K
Kirill Batuzov 已提交
585

586
    for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
587
        tcg_target_ulong mask, partmask, affected;
588
        int nb_oargs, nb_iargs, i;
589 590
        TCGArg tmp;

591 592 593 594 595 596
        TCGOp * const op = &s->gen_op_buf[oi];
        TCGArg * const args = &s->gen_opparam_buf[op->args];
        TCGOpcode opc = op->opc;
        const TCGOpDef *def = &tcg_op_defs[opc];

        oi_next = op->next;
597 598 599

        /* Count the arguments, and initialize the temps that are
           going to be used */
600 601 602
        if (opc == INDEX_op_call) {
            nb_oargs = op->callo;
            nb_iargs = op->calli;
603 604 605 606 607 608
            for (i = 0; i < nb_oargs + nb_iargs; i++) {
                tmp = args[i];
                if (tmp != TCG_CALL_DUMMY_ARG) {
                    init_temp_info(tmp);
                }
            }
609
        } else {
610 611
            nb_oargs = def->nb_oargs;
            nb_iargs = def->nb_iargs;
612 613 614
            for (i = 0; i < nb_oargs + nb_iargs; i++) {
                init_temp_info(args[i]);
            }
615 616 617 618
        }

        /* Do copy propagation */
        for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) {
619
            if (temp_is_copy(args[i])) {
620
                args[i] = find_better_copy(s, args[i]);
621 622 623
            }
        }

624
        /* For commutative operations make constant second argument */
625
        switch (opc) {
626 627
        CASE_OP_32_64(add):
        CASE_OP_32_64(mul):
628 629 630
        CASE_OP_32_64(and):
        CASE_OP_32_64(or):
        CASE_OP_32_64(xor):
631 632 633
        CASE_OP_32_64(eqv):
        CASE_OP_32_64(nand):
        CASE_OP_32_64(nor):
634 635
        CASE_OP_32_64(muluh):
        CASE_OP_32_64(mulsh):
636
            swap_commutative(args[0], &args[1], &args[2]);
637
            break;
638
        CASE_OP_32_64(brcond):
639
            if (swap_commutative(-1, &args[0], &args[1])) {
640 641 642 643
                args[2] = tcg_swap_cond(args[2]);
            }
            break;
        CASE_OP_32_64(setcond):
644
            if (swap_commutative(args[0], &args[1], &args[2])) {
645 646 647
                args[3] = tcg_swap_cond(args[3]);
            }
            break;
648
        CASE_OP_32_64(movcond):
649 650
            if (swap_commutative(-1, &args[1], &args[2])) {
                args[5] = tcg_swap_cond(args[5]);
651 652 653 654
            }
            /* For movcond, we canonicalize the "false" input reg to match
               the destination reg so that the tcg backend can implement
               a "move if true" operation.  */
655 656
            if (swap_commutative(args[0], &args[4], &args[3])) {
                args[5] = tcg_invert_cond(args[5]);
657
            }
658
            break;
659
        CASE_OP_32_64(add2):
660 661 662
            swap_commutative(args[0], &args[2], &args[4]);
            swap_commutative(args[1], &args[3], &args[5]);
            break;
663
        CASE_OP_32_64(mulu2):
664
        CASE_OP_32_64(muls2):
R
Richard Henderson 已提交
665 666
            swap_commutative(args[0], &args[2], &args[3]);
            break;
667 668 669 670 671 672 673 674 675 676
        case INDEX_op_brcond2_i32:
            if (swap_commutative2(&args[0], &args[2])) {
                args[4] = tcg_swap_cond(args[4]);
            }
            break;
        case INDEX_op_setcond2_i32:
            if (swap_commutative2(&args[1], &args[3])) {
                args[5] = tcg_swap_cond(args[5]);
            }
            break;
677 678 679 680
        default:
            break;
        }

681 682
        /* Simplify expressions for "shift/rot r, 0, a => movi r, 0",
           and "sub r, 0, a => neg r, a" case.  */
683
        switch (opc) {
684 685 686 687 688
        CASE_OP_32_64(shl):
        CASE_OP_32_64(shr):
        CASE_OP_32_64(sar):
        CASE_OP_32_64(rotl):
        CASE_OP_32_64(rotr):
689
            if (temp_is_const(args[1]) && temps[args[1]].val == 0) {
690
                tcg_opt_gen_movi(s, op, args, args[0], 0);
691 692 693
                continue;
            }
            break;
694 695 696 697 698
        CASE_OP_32_64(sub):
            {
                TCGOpcode neg_op;
                bool have_neg;

699
                if (temp_is_const(args[2])) {
700 701 702
                    /* Proceed with possible constant folding. */
                    break;
                }
703
                if (opc == INDEX_op_sub_i32) {
704 705 706 707 708 709 710 711 712
                    neg_op = INDEX_op_neg_i32;
                    have_neg = TCG_TARGET_HAS_neg_i32;
                } else {
                    neg_op = INDEX_op_neg_i64;
                    have_neg = TCG_TARGET_HAS_neg_i64;
                }
                if (!have_neg) {
                    break;
                }
713
                if (temp_is_const(args[1]) && temps[args[1]].val == 0) {
714
                    op->opc = neg_op;
715
                    reset_temp(args[0]);
716
                    args[1] = args[2];
717 718 719 720
                    continue;
                }
            }
            break;
721 722
        CASE_OP_32_64(xor):
        CASE_OP_32_64(nand):
723 724
            if (!temp_is_const(args[1])
                && temp_is_const(args[2]) && temps[args[2]].val == -1) {
725 726 727 728 729
                i = 1;
                goto try_not;
            }
            break;
        CASE_OP_32_64(nor):
730 731
            if (!temp_is_const(args[1])
                && temp_is_const(args[2]) && temps[args[2]].val == 0) {
732 733 734 735 736
                i = 1;
                goto try_not;
            }
            break;
        CASE_OP_32_64(andc):
737 738
            if (!temp_is_const(args[2])
                && temp_is_const(args[1]) && temps[args[1]].val == -1) {
739 740 741 742 743 744
                i = 2;
                goto try_not;
            }
            break;
        CASE_OP_32_64(orc):
        CASE_OP_32_64(eqv):
745 746
            if (!temp_is_const(args[2])
                && temp_is_const(args[1]) && temps[args[1]].val == 0) {
747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
                i = 2;
                goto try_not;
            }
            break;
        try_not:
            {
                TCGOpcode not_op;
                bool have_not;

                if (def->flags & TCG_OPF_64BIT) {
                    not_op = INDEX_op_not_i64;
                    have_not = TCG_TARGET_HAS_not_i64;
                } else {
                    not_op = INDEX_op_not_i32;
                    have_not = TCG_TARGET_HAS_not_i32;
                }
                if (!have_not) {
                    break;
                }
766
                op->opc = not_op;
767
                reset_temp(args[0]);
768
                args[1] = args[i];
769 770
                continue;
            }
771 772 773 774
        default:
            break;
        }

775
        /* Simplify expression for "op r, a, const => mov r, a" cases */
776
        switch (opc) {
777 778
        CASE_OP_32_64(add):
        CASE_OP_32_64(sub):
779 780 781
        CASE_OP_32_64(shl):
        CASE_OP_32_64(shr):
        CASE_OP_32_64(sar):
782 783
        CASE_OP_32_64(rotl):
        CASE_OP_32_64(rotr):
784 785
        CASE_OP_32_64(or):
        CASE_OP_32_64(xor):
786
        CASE_OP_32_64(andc):
787 788
            if (!temp_is_const(args[1])
                && temp_is_const(args[2]) && temps[args[2]].val == 0) {
789 790
                tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                continue;
791 792
            }
            break;
793 794 795
        CASE_OP_32_64(and):
        CASE_OP_32_64(orc):
        CASE_OP_32_64(eqv):
796 797
            if (!temp_is_const(args[1])
                && temp_is_const(args[2]) && temps[args[2]].val == -1) {
798 799
                tcg_opt_gen_mov(s, op, args, args[0], args[1]);
                continue;
800 801
            }
            break;
802 803 804 805
        default:
            break;
        }

806 807
        /* Simplify using known-zero bits. Currently only ops with a single
           output argument is supported. */
808
        mask = -1;
809
        affected = -1;
810
        switch (opc) {
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834
        CASE_OP_32_64(ext8s):
            if ((temps[args[1]].mask & 0x80) != 0) {
                break;
            }
        CASE_OP_32_64(ext8u):
            mask = 0xff;
            goto and_const;
        CASE_OP_32_64(ext16s):
            if ((temps[args[1]].mask & 0x8000) != 0) {
                break;
            }
        CASE_OP_32_64(ext16u):
            mask = 0xffff;
            goto and_const;
        case INDEX_op_ext32s_i64:
            if ((temps[args[1]].mask & 0x80000000) != 0) {
                break;
            }
        case INDEX_op_ext32u_i64:
            mask = 0xffffffffU;
            goto and_const;

        CASE_OP_32_64(and):
            mask = temps[args[2]].mask;
835
            if (temp_is_const(args[2])) {
836
        and_const:
837
                affected = temps[args[1]].mask & ~mask;
838 839 840 841
            }
            mask = temps[args[1]].mask & mask;
            break;

842 843 844 845 846 847 848 849 850
        case INDEX_op_ext_i32_i64:
            if ((temps[args[1]].mask & 0x80000000) != 0) {
                break;
            }
        case INDEX_op_extu_i32_i64:
            /* We do not compute affected as it is a size changing op.  */
            mask = (uint32_t)temps[args[1]].mask;
            break;

851 852 853
        CASE_OP_32_64(andc):
            /* Known-zeros does not imply known-ones.  Therefore unless
               args[2] is constant, we can't infer anything from it.  */
854
            if (temp_is_const(args[2])) {
855 856 857 858 859 860 861
                mask = ~temps[args[2]].mask;
                goto and_const;
            }
            /* But we certainly know nothing outside args[1] may be set. */
            mask = temps[args[1]].mask;
            break;

862
        case INDEX_op_sar_i32:
863
            if (temp_is_const(args[2])) {
864 865
                tmp = temps[args[2]].val & 31;
                mask = (int32_t)temps[args[1]].mask >> tmp;
866 867 868
            }
            break;
        case INDEX_op_sar_i64:
869
            if (temp_is_const(args[2])) {
870 871
                tmp = temps[args[2]].val & 63;
                mask = (int64_t)temps[args[1]].mask >> tmp;
872 873 874
            }
            break;

875
        case INDEX_op_shr_i32:
876
            if (temp_is_const(args[2])) {
877 878
                tmp = temps[args[2]].val & 31;
                mask = (uint32_t)temps[args[1]].mask >> tmp;
879 880 881
            }
            break;
        case INDEX_op_shr_i64:
882
            if (temp_is_const(args[2])) {
883 884
                tmp = temps[args[2]].val & 63;
                mask = (uint64_t)temps[args[1]].mask >> tmp;
885 886 887
            }
            break;

888 889 890 891 892
        case INDEX_op_extrl_i64_i32:
            mask = (uint32_t)temps[args[1]].mask;
            break;
        case INDEX_op_extrh_i64_i32:
            mask = (uint64_t)temps[args[1]].mask >> 32;
893 894
            break;

895
        CASE_OP_32_64(shl):
896
            if (temp_is_const(args[2])) {
897 898
                tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1);
                mask = temps[args[1]].mask << tmp;
899 900 901 902 903 904 905 906 907
            }
            break;

        CASE_OP_32_64(neg):
            /* Set to 1 all bits to the left of the rightmost.  */
            mask = -(temps[args[1]].mask & -temps[args[1]].mask);
            break;

        CASE_OP_32_64(deposit):
908 909
            mask = deposit64(temps[args[1]].mask, args[3], args[4],
                             temps[args[2]].mask);
910 911 912 913 914 915 916 917
            break;

        CASE_OP_32_64(or):
        CASE_OP_32_64(xor):
            mask = temps[args[1]].mask | temps[args[2]].mask;
            break;

        CASE_OP_32_64(setcond):
918
        case INDEX_op_setcond2_i32:
919 920 921 922 923 924 925
            mask = 1;
            break;

        CASE_OP_32_64(movcond):
            mask = temps[args[3]].mask | temps[args[4]].mask;
            break;

926 927 928 929 930 931 932 933 934 935 936 937
        CASE_OP_32_64(ld8u):
            mask = 0xff;
            break;
        CASE_OP_32_64(ld16u):
            mask = 0xffff;
            break;
        case INDEX_op_ld32u_i64:
            mask = 0xffffffffu;
            break;

        CASE_OP_32_64(qemu_ld):
            {
938 939
                TCGMemOpIdx oi = args[nb_oargs + nb_iargs];
                TCGMemOp mop = get_memop(oi);
940 941 942 943 944 945
                if (!(mop & MO_SIGN)) {
                    mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1;
                }
            }
            break;

946 947 948 949
        default:
            break;
        }

950 951 952
        /* 32-bit ops generate 32-bit results.  For the result is zero test
           below, we can ignore high bits, but for further optimizations we
           need to record that the high bits contain garbage.  */
953
        partmask = mask;
954
        if (!(def->flags & TCG_OPF_64BIT)) {
955 956 957
            mask |= ~(tcg_target_ulong)0xffffffffu;
            partmask &= 0xffffffffu;
            affected &= 0xffffffffu;
958 959
        }

960
        if (partmask == 0) {
961
            tcg_debug_assert(nb_oargs == 1);
962
            tcg_opt_gen_movi(s, op, args, args[0], 0);
963 964 965
            continue;
        }
        if (affected == 0) {
966
            tcg_debug_assert(nb_oargs == 1);
967
            tcg_opt_gen_mov(s, op, args, args[0], args[1]);
968 969 970
            continue;
        }

971
        /* Simplify expression for "op r, a, 0 => movi r, 0" cases */
972
        switch (opc) {
973
        CASE_OP_32_64(and):
974
        CASE_OP_32_64(mul):
975 976
        CASE_OP_32_64(muluh):
        CASE_OP_32_64(mulsh):
977
            if ((temp_is_const(args[2]) && temps[args[2]].val == 0)) {
978
                tcg_opt_gen_movi(s, op, args, args[0], 0);
979 980 981
                continue;
            }
            break;
982 983 984 985 986
        default:
            break;
        }

        /* Simplify expression for "op r, a, a => mov r, a" cases */
987
        switch (opc) {
988 989
        CASE_OP_32_64(or):
        CASE_OP_32_64(and):
990
            if (temps_are_copies(args[1], args[2])) {
991
                tcg_opt_gen_mov(s, op, args, args[0], args[1]);
992 993 994
                continue;
            }
            break;
B
Blue Swirl 已提交
995 996
        default:
            break;
997 998
        }

999
        /* Simplify expression for "op r, a, a => movi r, 0" cases */
1000
        switch (opc) {
1001
        CASE_OP_32_64(andc):
1002 1003 1004
        CASE_OP_32_64(sub):
        CASE_OP_32_64(xor):
            if (temps_are_copies(args[1], args[2])) {
1005
                tcg_opt_gen_movi(s, op, args, args[0], 0);
1006 1007 1008 1009 1010 1011 1012
                continue;
            }
            break;
        default:
            break;
        }

1013 1014 1015
        /* Propagate constants through copy operations and do constant
           folding.  Constants will be substituted to arguments by register
           allocator where needed and possible.  Also detect copies. */
1016
        switch (opc) {
1017
        CASE_OP_32_64(mov):
1018 1019
            tcg_opt_gen_mov(s, op, args, args[0], args[1]);
            break;
1020
        CASE_OP_32_64(movi):
1021
            tcg_opt_gen_movi(s, op, args, args[0], args[1]);
1022
            break;
1023

1024
        CASE_OP_32_64(not):
1025
        CASE_OP_32_64(neg):
1026 1027 1028 1029
        CASE_OP_32_64(ext8s):
        CASE_OP_32_64(ext8u):
        CASE_OP_32_64(ext16s):
        CASE_OP_32_64(ext16u):
1030 1031
        case INDEX_op_ext32s_i64:
        case INDEX_op_ext32u_i64:
1032 1033
        case INDEX_op_ext_i32_i64:
        case INDEX_op_extu_i32_i64:
1034 1035
        case INDEX_op_extrl_i64_i32:
        case INDEX_op_extrh_i64_i32:
1036
            if (temp_is_const(args[1])) {
1037
                tmp = do_constant_folding(opc, temps[args[1]].val, 0);
1038
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
1039
                break;
1040
            }
1041 1042
            goto do_default;

1043 1044 1045
        CASE_OP_32_64(add):
        CASE_OP_32_64(sub):
        CASE_OP_32_64(mul):
1046 1047 1048
        CASE_OP_32_64(or):
        CASE_OP_32_64(and):
        CASE_OP_32_64(xor):
1049 1050 1051
        CASE_OP_32_64(shl):
        CASE_OP_32_64(shr):
        CASE_OP_32_64(sar):
1052 1053
        CASE_OP_32_64(rotl):
        CASE_OP_32_64(rotr):
1054 1055 1056 1057 1058
        CASE_OP_32_64(andc):
        CASE_OP_32_64(orc):
        CASE_OP_32_64(eqv):
        CASE_OP_32_64(nand):
        CASE_OP_32_64(nor):
1059 1060
        CASE_OP_32_64(muluh):
        CASE_OP_32_64(mulsh):
R
Richard Henderson 已提交
1061 1062 1063 1064
        CASE_OP_32_64(div):
        CASE_OP_32_64(divu):
        CASE_OP_32_64(rem):
        CASE_OP_32_64(remu):
1065
            if (temp_is_const(args[1]) && temp_is_const(args[2])) {
1066
                tmp = do_constant_folding(opc, temps[args[1]].val,
1067
                                          temps[args[2]].val);
1068
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
1069
                break;
1070
            }
1071 1072
            goto do_default;

1073
        CASE_OP_32_64(deposit):
1074
            if (temp_is_const(args[1]) && temp_is_const(args[2])) {
1075 1076
                tmp = deposit64(temps[args[1]].val, args[3], args[4],
                                temps[args[2]].val);
1077
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
1078
                break;
1079
            }
1080 1081
            goto do_default;

1082
        CASE_OP_32_64(setcond):
1083
            tmp = do_constant_folding_cond(opc, args[1], args[2], args[3]);
1084
            if (tmp != 2) {
1085
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
1086
                break;
1087
            }
1088 1089
            goto do_default;

1090
        CASE_OP_32_64(brcond):
1091
            tmp = do_constant_folding_cond(opc, args[0], args[1], args[2]);
1092 1093
            if (tmp != 2) {
                if (tmp) {
1094
                    reset_all_temps(nb_temps);
1095 1096
                    op->opc = INDEX_op_br;
                    args[0] = args[3];
1097
                } else {
1098
                    tcg_op_remove(s, op);
1099
                }
1100
                break;
1101
            }
1102 1103
            goto do_default;

1104
        CASE_OP_32_64(movcond):
1105
            tmp = do_constant_folding_cond(opc, args[1], args[2], args[5]);
1106
            if (tmp != 2) {
1107
                tcg_opt_gen_mov(s, op, args, args[0], args[4-tmp]);
1108
                break;
1109
            }
1110
            goto do_default;
1111 1112 1113

        case INDEX_op_add2_i32:
        case INDEX_op_sub2_i32:
1114 1115
            if (temp_is_const(args[2]) && temp_is_const(args[3])
                && temp_is_const(args[4]) && temp_is_const(args[5])) {
1116 1117 1118 1119 1120 1121 1122
                uint32_t al = temps[args[2]].val;
                uint32_t ah = temps[args[3]].val;
                uint32_t bl = temps[args[4]].val;
                uint32_t bh = temps[args[5]].val;
                uint64_t a = ((uint64_t)ah << 32) | al;
                uint64_t b = ((uint64_t)bh << 32) | bl;
                TCGArg rl, rh;
1123 1124
                TCGOp *op2 = insert_op_before(s, op, INDEX_op_movi_i32, 2);
                TCGArg *args2 = &s->gen_opparam_buf[op2->args];
1125

1126
                if (opc == INDEX_op_add2_i32) {
1127 1128 1129 1130 1131 1132 1133
                    a += b;
                } else {
                    a -= b;
                }

                rl = args[0];
                rh = args[1];
1134 1135
                tcg_opt_gen_movi(s, op, args, rl, (int32_t)a);
                tcg_opt_gen_movi(s, op2, args2, rh, (int32_t)(a >> 32));
1136 1137 1138

                /* We've done all we need to do with the movi.  Skip it.  */
                oi_next = op2->next;
1139 1140 1141
                break;
            }
            goto do_default;
R
Richard Henderson 已提交
1142 1143

        case INDEX_op_mulu2_i32:
1144
            if (temp_is_const(args[2]) && temp_is_const(args[3])) {
R
Richard Henderson 已提交
1145 1146 1147 1148
                uint32_t a = temps[args[2]].val;
                uint32_t b = temps[args[3]].val;
                uint64_t r = (uint64_t)a * b;
                TCGArg rl, rh;
1149 1150
                TCGOp *op2 = insert_op_before(s, op, INDEX_op_movi_i32, 2);
                TCGArg *args2 = &s->gen_opparam_buf[op2->args];
R
Richard Henderson 已提交
1151 1152 1153

                rl = args[0];
                rh = args[1];
1154 1155
                tcg_opt_gen_movi(s, op, args, rl, (int32_t)r);
                tcg_opt_gen_movi(s, op2, args2, rh, (int32_t)(r >> 32));
1156 1157 1158

                /* We've done all we need to do with the movi.  Skip it.  */
                oi_next = op2->next;
R
Richard Henderson 已提交
1159 1160 1161
                break;
            }
            goto do_default;
1162

1163
        case INDEX_op_brcond2_i32:
1164 1165 1166
            tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]);
            if (tmp != 2) {
                if (tmp) {
1167
            do_brcond_true:
1168
                    reset_all_temps(nb_temps);
1169 1170
                    op->opc = INDEX_op_br;
                    args[0] = args[5];
1171
                } else {
1172
            do_brcond_false:
1173
                    tcg_op_remove(s, op);
1174 1175
                }
            } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE)
1176 1177
                       && temp_is_const(args[2]) && temps[args[2]].val == 0
                       && temp_is_const(args[3]) && temps[args[3]].val == 0) {
1178 1179
                /* Simplify LT/GE comparisons vs zero to a single compare
                   vs the high word of the input.  */
1180
            do_brcond_high:
1181
                reset_all_temps(nb_temps);
1182 1183 1184 1185 1186
                op->opc = INDEX_op_brcond_i32;
                args[0] = args[1];
                args[1] = args[3];
                args[2] = args[4];
                args[3] = args[5];
1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205
            } else if (args[4] == TCG_COND_EQ) {
                /* Simplify EQ comparisons where one of the pairs
                   can be simplified.  */
                tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
                                               args[0], args[2], TCG_COND_EQ);
                if (tmp == 0) {
                    goto do_brcond_false;
                } else if (tmp == 1) {
                    goto do_brcond_high;
                }
                tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
                                               args[1], args[3], TCG_COND_EQ);
                if (tmp == 0) {
                    goto do_brcond_false;
                } else if (tmp != 1) {
                    goto do_default;
                }
            do_brcond_low:
                reset_all_temps(nb_temps);
1206 1207 1208 1209
                op->opc = INDEX_op_brcond_i32;
                args[1] = args[2];
                args[2] = args[4];
                args[3] = args[5];
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
            } else if (args[4] == TCG_COND_NE) {
                /* Simplify NE comparisons where one of the pairs
                   can be simplified.  */
                tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
                                               args[0], args[2], TCG_COND_NE);
                if (tmp == 0) {
                    goto do_brcond_high;
                } else if (tmp == 1) {
                    goto do_brcond_true;
                }
                tmp = do_constant_folding_cond(INDEX_op_brcond_i32,
                                               args[1], args[3], TCG_COND_NE);
                if (tmp == 0) {
                    goto do_brcond_low;
                } else if (tmp == 1) {
                    goto do_brcond_true;
                }
                goto do_default;
1228 1229
            } else {
                goto do_default;
1230
            }
1231
            break;
1232 1233

        case INDEX_op_setcond2_i32:
1234 1235
            tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]);
            if (tmp != 2) {
1236
            do_setcond_const:
1237
                tcg_opt_gen_movi(s, op, args, args[0], tmp);
1238
            } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE)
1239 1240
                       && temp_is_const(args[3]) && temps[args[3]].val == 0
                       && temp_is_const(args[4]) && temps[args[4]].val == 0) {
1241 1242
                /* Simplify LT/GE comparisons vs zero to a single compare
                   vs the high word of the input.  */
1243
            do_setcond_high:
1244
                reset_temp(args[0]);
1245
                temps[args[0]].mask = 1;
1246 1247 1248 1249
                op->opc = INDEX_op_setcond_i32;
                args[1] = args[2];
                args[2] = args[4];
                args[3] = args[5];
1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
            } else if (args[5] == TCG_COND_EQ) {
                /* Simplify EQ comparisons where one of the pairs
                   can be simplified.  */
                tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
                                               args[1], args[3], TCG_COND_EQ);
                if (tmp == 0) {
                    goto do_setcond_const;
                } else if (tmp == 1) {
                    goto do_setcond_high;
                }
                tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
                                               args[2], args[4], TCG_COND_EQ);
                if (tmp == 0) {
                    goto do_setcond_high;
                } else if (tmp != 1) {
                    goto do_default;
                }
            do_setcond_low:
                reset_temp(args[0]);
                temps[args[0]].mask = 1;
1270 1271 1272
                op->opc = INDEX_op_setcond_i32;
                args[2] = args[3];
                args[3] = args[5];
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290
            } else if (args[5] == TCG_COND_NE) {
                /* Simplify NE comparisons where one of the pairs
                   can be simplified.  */
                tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
                                               args[1], args[3], TCG_COND_NE);
                if (tmp == 0) {
                    goto do_setcond_high;
                } else if (tmp == 1) {
                    goto do_setcond_const;
                }
                tmp = do_constant_folding_cond(INDEX_op_setcond_i32,
                                               args[2], args[4], TCG_COND_NE);
                if (tmp == 0) {
                    goto do_setcond_low;
                } else if (tmp == 1) {
                    goto do_setcond_const;
                }
                goto do_default;
1291 1292
            } else {
                goto do_default;
1293
            }
1294
            break;
1295

K
Kirill Batuzov 已提交
1296
        case INDEX_op_call:
1297 1298
            if (!(args[nb_oargs + nb_iargs + 1]
                  & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) {
1299
                for (i = 0; i < nb_globals; i++) {
1300 1301 1302
                    if (test_bit(i, temps_used.l)) {
                        reset_temp(i);
                    }
1303 1304
                }
            }
1305
            goto do_reset_output;
1306

K
Kirill Batuzov 已提交
1307
        default:
1308 1309 1310 1311
        do_default:
            /* Default case: we know nothing about operation (or were unable
               to compute the operation result) so no propagation is done.
               We trash everything if the operation is the end of a basic
1312 1313
               block, otherwise we only trash the output args.  "mask" is
               the non-zero bits mask for the first output arg.  */
1314
            if (def->flags & TCG_OPF_BB_END) {
1315
                reset_all_temps(nb_temps);
1316
            } else {
1317 1318
        do_reset_output:
                for (i = 0; i < nb_oargs; i++) {
1319
                    reset_temp(args[i]);
1320 1321 1322 1323 1324
                    /* Save the corresponding known-zero bits mask for the
                       first output argument (only one supported so far). */
                    if (i == 0) {
                        temps[args[i]].mask = mask;
                    }
1325
                }
1326
            }
K
Kirill Batuzov 已提交
1327 1328 1329 1330
            break;
        }
    }
}