1 /* 2 * Optimizations for Tiny Code Generator for QEMU 3 * 4 * Copyright (c) 2010 Samsung Electronics. 5 * Contributed by Kirill Batuzov <batuzovk@ispras.ru> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26 #include "config.h" 27 28 #include <stdlib.h> 29 #include <stdio.h> 30 31 #include "qemu-common.h" 32 #include "tcg-op.h" 33 34 #define CASE_OP_32_64(x) \ 35 glue(glue(case INDEX_op_, x), _i32): \ 36 glue(glue(case INDEX_op_, x), _i64) 37 38 typedef enum { 39 TCG_TEMP_UNDEF = 0, 40 TCG_TEMP_CONST, 41 TCG_TEMP_COPY, 42 } tcg_temp_state; 43 44 struct tcg_temp_info { 45 tcg_temp_state state; 46 uint16_t prev_copy; 47 uint16_t next_copy; 48 tcg_target_ulong val; 49 tcg_target_ulong mask; 50 }; 51 52 static struct tcg_temp_info temps[TCG_MAX_TEMPS]; 53 54 /* Reset TEMP's state to TCG_TEMP_UNDEF. If TEMP only had one copy, remove 55 the copy flag from the left temp. */ 56 static void reset_temp(TCGArg temp) 57 { 58 if (temps[temp].state == TCG_TEMP_COPY) { 59 if (temps[temp].prev_copy == temps[temp].next_copy) { 60 temps[temps[temp].next_copy].state = TCG_TEMP_UNDEF; 61 } else { 62 temps[temps[temp].next_copy].prev_copy = temps[temp].prev_copy; 63 temps[temps[temp].prev_copy].next_copy = temps[temp].next_copy; 64 } 65 } 66 temps[temp].state = TCG_TEMP_UNDEF; 67 temps[temp].mask = -1; 68 } 69 70 /* Reset all temporaries, given that there are NB_TEMPS of them. */ 71 static void reset_all_temps(int nb_temps) 72 { 73 int i; 74 for (i = 0; i < nb_temps; i++) { 75 temps[i].state = TCG_TEMP_UNDEF; 76 temps[i].mask = -1; 77 } 78 } 79 80 static int op_bits(TCGOpcode op) 81 { 82 const TCGOpDef *def = &tcg_op_defs[op]; 83 return def->flags & TCG_OPF_64BIT ? 64 : 32; 84 } 85 86 static TCGOpcode op_to_mov(TCGOpcode op) 87 { 88 switch (op_bits(op)) { 89 case 32: 90 return INDEX_op_mov_i32; 91 case 64: 92 return INDEX_op_mov_i64; 93 default: 94 fprintf(stderr, "op_to_mov: unexpected return value of " 95 "function op_bits.\n"); 96 tcg_abort(); 97 } 98 } 99 100 static TCGOpcode op_to_movi(TCGOpcode op) 101 { 102 switch (op_bits(op)) { 103 case 32: 104 return INDEX_op_movi_i32; 105 case 64: 106 return INDEX_op_movi_i64; 107 default: 108 fprintf(stderr, "op_to_movi: unexpected return value of " 109 "function op_bits.\n"); 110 tcg_abort(); 111 } 112 } 113 114 static TCGArg find_better_copy(TCGContext *s, TCGArg temp) 115 { 116 TCGArg i; 117 118 /* If this is already a global, we can't do better. */ 119 if (temp < s->nb_globals) { 120 return temp; 121 } 122 123 /* Search for a global first. */ 124 for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) { 125 if (i < s->nb_globals) { 126 return i; 127 } 128 } 129 130 /* If it is a temp, search for a temp local. */ 131 if (!s->temps[temp].temp_local) { 132 for (i = temps[temp].next_copy ; i != temp ; i = temps[i].next_copy) { 133 if (s->temps[i].temp_local) { 134 return i; 135 } 136 } 137 } 138 139 /* Failure to find a better representation, return the same temp. */ 140 return temp; 141 } 142 143 static bool temps_are_copies(TCGArg arg1, TCGArg arg2) 144 { 145 TCGArg i; 146 147 if (arg1 == arg2) { 148 return true; 149 } 150 151 if (temps[arg1].state != TCG_TEMP_COPY 152 || temps[arg2].state != TCG_TEMP_COPY) { 153 return false; 154 } 155 156 for (i = temps[arg1].next_copy ; i != arg1 ; i = temps[i].next_copy) { 157 if (i == arg2) { 158 return true; 159 } 160 } 161 162 return false; 163 } 164 165 static void tcg_opt_gen_mov(TCGContext *s, int op_index, TCGArg *gen_args, 166 TCGOpcode old_op, TCGArg dst, TCGArg src) 167 { 168 TCGOpcode new_op = op_to_mov(old_op); 169 tcg_target_ulong mask; 170 171 s->gen_opc_buf[op_index] = new_op; 172 173 reset_temp(dst); 174 mask = temps[src].mask; 175 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) { 176 /* High bits of the destination are now garbage. */ 177 mask |= ~0xffffffffull; 178 } 179 temps[dst].mask = mask; 180 181 assert(temps[src].state != TCG_TEMP_CONST); 182 183 if (s->temps[src].type == s->temps[dst].type) { 184 if (temps[src].state != TCG_TEMP_COPY) { 185 temps[src].state = TCG_TEMP_COPY; 186 temps[src].next_copy = src; 187 temps[src].prev_copy = src; 188 } 189 temps[dst].state = TCG_TEMP_COPY; 190 temps[dst].next_copy = temps[src].next_copy; 191 temps[dst].prev_copy = src; 192 temps[temps[dst].next_copy].prev_copy = dst; 193 temps[src].next_copy = dst; 194 } 195 196 gen_args[0] = dst; 197 gen_args[1] = src; 198 } 199 200 static void tcg_opt_gen_movi(TCGContext *s, int op_index, TCGArg *gen_args, 201 TCGOpcode old_op, TCGArg dst, TCGArg val) 202 { 203 TCGOpcode new_op = op_to_movi(old_op); 204 tcg_target_ulong mask; 205 206 s->gen_opc_buf[op_index] = new_op; 207 208 reset_temp(dst); 209 temps[dst].state = TCG_TEMP_CONST; 210 temps[dst].val = val; 211 mask = val; 212 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) { 213 /* High bits of the destination are now garbage. */ 214 mask |= ~0xffffffffull; 215 } 216 temps[dst].mask = mask; 217 218 gen_args[0] = dst; 219 gen_args[1] = val; 220 } 221 222 static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) 223 { 224 uint64_t l64, h64; 225 226 switch (op) { 227 CASE_OP_32_64(add): 228 return x + y; 229 230 CASE_OP_32_64(sub): 231 return x - y; 232 233 CASE_OP_32_64(mul): 234 return x * y; 235 236 CASE_OP_32_64(and): 237 return x & y; 238 239 CASE_OP_32_64(or): 240 return x | y; 241 242 CASE_OP_32_64(xor): 243 return x ^ y; 244 245 case INDEX_op_shl_i32: 246 return (uint32_t)x << (y & 31); 247 248 case INDEX_op_shl_i64: 249 return (uint64_t)x << (y & 63); 250 251 case INDEX_op_shr_i32: 252 return (uint32_t)x >> (y & 31); 253 254 case INDEX_op_trunc_shr_i32: 255 case INDEX_op_shr_i64: 256 return (uint64_t)x >> (y & 63); 257 258 case INDEX_op_sar_i32: 259 return (int32_t)x >> (y & 31); 260 261 case INDEX_op_sar_i64: 262 return (int64_t)x >> (y & 63); 263 264 case INDEX_op_rotr_i32: 265 return ror32(x, y & 31); 266 267 case INDEX_op_rotr_i64: 268 return ror64(x, y & 63); 269 270 case INDEX_op_rotl_i32: 271 return rol32(x, y & 31); 272 273 case INDEX_op_rotl_i64: 274 return rol64(x, y & 63); 275 276 CASE_OP_32_64(not): 277 return ~x; 278 279 CASE_OP_32_64(neg): 280 return -x; 281 282 CASE_OP_32_64(andc): 283 return x & ~y; 284 285 CASE_OP_32_64(orc): 286 return x | ~y; 287 288 CASE_OP_32_64(eqv): 289 return ~(x ^ y); 290 291 CASE_OP_32_64(nand): 292 return ~(x & y); 293 294 CASE_OP_32_64(nor): 295 return ~(x | y); 296 297 CASE_OP_32_64(ext8s): 298 return (int8_t)x; 299 300 CASE_OP_32_64(ext16s): 301 return (int16_t)x; 302 303 CASE_OP_32_64(ext8u): 304 return (uint8_t)x; 305 306 CASE_OP_32_64(ext16u): 307 return (uint16_t)x; 308 309 case INDEX_op_ext32s_i64: 310 return (int32_t)x; 311 312 case INDEX_op_ext32u_i64: 313 return (uint32_t)x; 314 315 case INDEX_op_muluh_i32: 316 return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32; 317 case INDEX_op_mulsh_i32: 318 return ((int64_t)(int32_t)x * (int32_t)y) >> 32; 319 320 case INDEX_op_muluh_i64: 321 mulu64(&l64, &h64, x, y); 322 return h64; 323 case INDEX_op_mulsh_i64: 324 muls64(&l64, &h64, x, y); 325 return h64; 326 327 case INDEX_op_div_i32: 328 /* Avoid crashing on divide by zero, otherwise undefined. */ 329 return (int32_t)x / ((int32_t)y ? : 1); 330 case INDEX_op_divu_i32: 331 return (uint32_t)x / ((uint32_t)y ? : 1); 332 case INDEX_op_div_i64: 333 return (int64_t)x / ((int64_t)y ? : 1); 334 case INDEX_op_divu_i64: 335 return (uint64_t)x / ((uint64_t)y ? : 1); 336 337 case INDEX_op_rem_i32: 338 return (int32_t)x % ((int32_t)y ? : 1); 339 case INDEX_op_remu_i32: 340 return (uint32_t)x % ((uint32_t)y ? : 1); 341 case INDEX_op_rem_i64: 342 return (int64_t)x % ((int64_t)y ? : 1); 343 case INDEX_op_remu_i64: 344 return (uint64_t)x % ((uint64_t)y ? : 1); 345 346 default: 347 fprintf(stderr, 348 "Unrecognized operation %d in do_constant_folding.\n", op); 349 tcg_abort(); 350 } 351 } 352 353 static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) 354 { 355 TCGArg res = do_constant_folding_2(op, x, y); 356 if (op_bits(op) == 32) { 357 res &= 0xffffffff; 358 } 359 return res; 360 } 361 362 static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c) 363 { 364 switch (c) { 365 case TCG_COND_EQ: 366 return x == y; 367 case TCG_COND_NE: 368 return x != y; 369 case TCG_COND_LT: 370 return (int32_t)x < (int32_t)y; 371 case TCG_COND_GE: 372 return (int32_t)x >= (int32_t)y; 373 case TCG_COND_LE: 374 return (int32_t)x <= (int32_t)y; 375 case TCG_COND_GT: 376 return (int32_t)x > (int32_t)y; 377 case TCG_COND_LTU: 378 return x < y; 379 case TCG_COND_GEU: 380 return x >= y; 381 case TCG_COND_LEU: 382 return x <= y; 383 case TCG_COND_GTU: 384 return x > y; 385 default: 386 tcg_abort(); 387 } 388 } 389 390 static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c) 391 { 392 switch (c) { 393 case TCG_COND_EQ: 394 return x == y; 395 case TCG_COND_NE: 396 return x != y; 397 case TCG_COND_LT: 398 return (int64_t)x < (int64_t)y; 399 case TCG_COND_GE: 400 return (int64_t)x >= (int64_t)y; 401 case TCG_COND_LE: 402 return (int64_t)x <= (int64_t)y; 403 case TCG_COND_GT: 404 return (int64_t)x > (int64_t)y; 405 case TCG_COND_LTU: 406 return x < y; 407 case TCG_COND_GEU: 408 return x >= y; 409 case TCG_COND_LEU: 410 return x <= y; 411 case TCG_COND_GTU: 412 return x > y; 413 default: 414 tcg_abort(); 415 } 416 } 417 418 static bool do_constant_folding_cond_eq(TCGCond c) 419 { 420 switch (c) { 421 case TCG_COND_GT: 422 case TCG_COND_LTU: 423 case TCG_COND_LT: 424 case TCG_COND_GTU: 425 case TCG_COND_NE: 426 return 0; 427 case TCG_COND_GE: 428 case TCG_COND_GEU: 429 case TCG_COND_LE: 430 case TCG_COND_LEU: 431 case TCG_COND_EQ: 432 return 1; 433 default: 434 tcg_abort(); 435 } 436 } 437 438 /* Return 2 if the condition can't be simplified, and the result 439 of the condition (0 or 1) if it can */ 440 static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, 441 TCGArg y, TCGCond c) 442 { 443 if (temps[x].state == TCG_TEMP_CONST && temps[y].state == TCG_TEMP_CONST) { 444 switch (op_bits(op)) { 445 case 32: 446 return do_constant_folding_cond_32(temps[x].val, temps[y].val, c); 447 case 64: 448 return do_constant_folding_cond_64(temps[x].val, temps[y].val, c); 449 default: 450 tcg_abort(); 451 } 452 } else if (temps_are_copies(x, y)) { 453 return do_constant_folding_cond_eq(c); 454 } else if (temps[y].state == TCG_TEMP_CONST && temps[y].val == 0) { 455 switch (c) { 456 case TCG_COND_LTU: 457 return 0; 458 case TCG_COND_GEU: 459 return 1; 460 default: 461 return 2; 462 } 463 } else { 464 return 2; 465 } 466 } 467 468 /* Return 2 if the condition can't be simplified, and the result 469 of the condition (0 or 1) if it can */ 470 static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c) 471 { 472 TCGArg al = p1[0], ah = p1[1]; 473 TCGArg bl = p2[0], bh = p2[1]; 474 475 if (temps[bl].state == TCG_TEMP_CONST 476 && temps[bh].state == TCG_TEMP_CONST) { 477 uint64_t b = ((uint64_t)temps[bh].val << 32) | (uint32_t)temps[bl].val; 478 479 if (temps[al].state == TCG_TEMP_CONST 480 && temps[ah].state == TCG_TEMP_CONST) { 481 uint64_t a; 482 a = ((uint64_t)temps[ah].val << 32) | (uint32_t)temps[al].val; 483 return do_constant_folding_cond_64(a, b, c); 484 } 485 if (b == 0) { 486 switch (c) { 487 case TCG_COND_LTU: 488 return 0; 489 case TCG_COND_GEU: 490 return 1; 491 default: 492 break; 493 } 494 } 495 } 496 if (temps_are_copies(al, bl) && temps_are_copies(ah, bh)) { 497 return do_constant_folding_cond_eq(c); 498 } 499 return 2; 500 } 501 502 static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) 503 { 504 TCGArg a1 = *p1, a2 = *p2; 505 int sum = 0; 506 sum += temps[a1].state == TCG_TEMP_CONST; 507 sum -= temps[a2].state == TCG_TEMP_CONST; 508 509 /* Prefer the constant in second argument, and then the form 510 op a, a, b, which is better handled on non-RISC hosts. */ 511 if (sum > 0 || (sum == 0 && dest == a2)) { 512 *p1 = a2; 513 *p2 = a1; 514 return true; 515 } 516 return false; 517 } 518 519 static bool swap_commutative2(TCGArg *p1, TCGArg *p2) 520 { 521 int sum = 0; 522 sum += temps[p1[0]].state == TCG_TEMP_CONST; 523 sum += temps[p1[1]].state == TCG_TEMP_CONST; 524 sum -= temps[p2[0]].state == TCG_TEMP_CONST; 525 sum -= temps[p2[1]].state == TCG_TEMP_CONST; 526 if (sum > 0) { 527 TCGArg t; 528 t = p1[0], p1[0] = p2[0], p2[0] = t; 529 t = p1[1], p1[1] = p2[1], p2[1] = t; 530 return true; 531 } 532 return false; 533 } 534 535 /* Propagate constants and copies, fold constant expressions. */ 536 static TCGArg *tcg_constant_folding(TCGContext *s, uint16_t *tcg_opc_ptr, 537 TCGArg *args, TCGOpDef *tcg_op_defs) 538 { 539 int nb_ops, op_index, nb_temps, nb_globals; 540 TCGArg *gen_args; 541 542 /* Array VALS has an element for each temp. 543 If this temp holds a constant then its value is kept in VALS' element. 544 If this temp is a copy of other ones then the other copies are 545 available through the doubly linked circular list. */ 546 547 nb_temps = s->nb_temps; 548 nb_globals = s->nb_globals; 549 reset_all_temps(nb_temps); 550 551 nb_ops = tcg_opc_ptr - s->gen_opc_buf; 552 gen_args = args; 553 for (op_index = 0; op_index < nb_ops; op_index++) { 554 TCGOpcode op = s->gen_opc_buf[op_index]; 555 const TCGOpDef *def = &tcg_op_defs[op]; 556 tcg_target_ulong mask, partmask, affected; 557 int nb_oargs, nb_iargs, nb_args, i; 558 TCGArg tmp; 559 560 if (op == INDEX_op_call) { 561 *gen_args++ = tmp = *args++; 562 nb_oargs = tmp >> 16; 563 nb_iargs = tmp & 0xffff; 564 nb_args = nb_oargs + nb_iargs + def->nb_cargs; 565 } else { 566 nb_oargs = def->nb_oargs; 567 nb_iargs = def->nb_iargs; 568 nb_args = def->nb_args; 569 } 570 571 /* Do copy propagation */ 572 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) { 573 if (temps[args[i]].state == TCG_TEMP_COPY) { 574 args[i] = find_better_copy(s, args[i]); 575 } 576 } 577 578 /* For commutative operations make constant second argument */ 579 switch (op) { 580 CASE_OP_32_64(add): 581 CASE_OP_32_64(mul): 582 CASE_OP_32_64(and): 583 CASE_OP_32_64(or): 584 CASE_OP_32_64(xor): 585 CASE_OP_32_64(eqv): 586 CASE_OP_32_64(nand): 587 CASE_OP_32_64(nor): 588 CASE_OP_32_64(muluh): 589 CASE_OP_32_64(mulsh): 590 swap_commutative(args[0], &args[1], &args[2]); 591 break; 592 CASE_OP_32_64(brcond): 593 if (swap_commutative(-1, &args[0], &args[1])) { 594 args[2] = tcg_swap_cond(args[2]); 595 } 596 break; 597 CASE_OP_32_64(setcond): 598 if (swap_commutative(args[0], &args[1], &args[2])) { 599 args[3] = tcg_swap_cond(args[3]); 600 } 601 break; 602 CASE_OP_32_64(movcond): 603 if (swap_commutative(-1, &args[1], &args[2])) { 604 args[5] = tcg_swap_cond(args[5]); 605 } 606 /* For movcond, we canonicalize the "false" input reg to match 607 the destination reg so that the tcg backend can implement 608 a "move if true" operation. */ 609 if (swap_commutative(args[0], &args[4], &args[3])) { 610 args[5] = tcg_invert_cond(args[5]); 611 } 612 break; 613 CASE_OP_32_64(add2): 614 swap_commutative(args[0], &args[2], &args[4]); 615 swap_commutative(args[1], &args[3], &args[5]); 616 break; 617 CASE_OP_32_64(mulu2): 618 CASE_OP_32_64(muls2): 619 swap_commutative(args[0], &args[2], &args[3]); 620 break; 621 case INDEX_op_brcond2_i32: 622 if (swap_commutative2(&args[0], &args[2])) { 623 args[4] = tcg_swap_cond(args[4]); 624 } 625 break; 626 case INDEX_op_setcond2_i32: 627 if (swap_commutative2(&args[1], &args[3])) { 628 args[5] = tcg_swap_cond(args[5]); 629 } 630 break; 631 default: 632 break; 633 } 634 635 /* Simplify expressions for "shift/rot r, 0, a => movi r, 0", 636 and "sub r, 0, a => neg r, a" case. */ 637 switch (op) { 638 CASE_OP_32_64(shl): 639 CASE_OP_32_64(shr): 640 CASE_OP_32_64(sar): 641 CASE_OP_32_64(rotl): 642 CASE_OP_32_64(rotr): 643 if (temps[args[1]].state == TCG_TEMP_CONST 644 && temps[args[1]].val == 0) { 645 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); 646 args += 3; 647 gen_args += 2; 648 continue; 649 } 650 break; 651 CASE_OP_32_64(sub): 652 { 653 TCGOpcode neg_op; 654 bool have_neg; 655 656 if (temps[args[2]].state == TCG_TEMP_CONST) { 657 /* Proceed with possible constant folding. */ 658 break; 659 } 660 if (op == INDEX_op_sub_i32) { 661 neg_op = INDEX_op_neg_i32; 662 have_neg = TCG_TARGET_HAS_neg_i32; 663 } else { 664 neg_op = INDEX_op_neg_i64; 665 have_neg = TCG_TARGET_HAS_neg_i64; 666 } 667 if (!have_neg) { 668 break; 669 } 670 if (temps[args[1]].state == TCG_TEMP_CONST 671 && temps[args[1]].val == 0) { 672 s->gen_opc_buf[op_index] = neg_op; 673 reset_temp(args[0]); 674 gen_args[0] = args[0]; 675 gen_args[1] = args[2]; 676 args += 3; 677 gen_args += 2; 678 continue; 679 } 680 } 681 break; 682 CASE_OP_32_64(xor): 683 CASE_OP_32_64(nand): 684 if (temps[args[1]].state != TCG_TEMP_CONST 685 && temps[args[2]].state == TCG_TEMP_CONST 686 && temps[args[2]].val == -1) { 687 i = 1; 688 goto try_not; 689 } 690 break; 691 CASE_OP_32_64(nor): 692 if (temps[args[1]].state != TCG_TEMP_CONST 693 && temps[args[2]].state == TCG_TEMP_CONST 694 && temps[args[2]].val == 0) { 695 i = 1; 696 goto try_not; 697 } 698 break; 699 CASE_OP_32_64(andc): 700 if (temps[args[2]].state != TCG_TEMP_CONST 701 && temps[args[1]].state == TCG_TEMP_CONST 702 && temps[args[1]].val == -1) { 703 i = 2; 704 goto try_not; 705 } 706 break; 707 CASE_OP_32_64(orc): 708 CASE_OP_32_64(eqv): 709 if (temps[args[2]].state != TCG_TEMP_CONST 710 && temps[args[1]].state == TCG_TEMP_CONST 711 && temps[args[1]].val == 0) { 712 i = 2; 713 goto try_not; 714 } 715 break; 716 try_not: 717 { 718 TCGOpcode not_op; 719 bool have_not; 720 721 if (def->flags & TCG_OPF_64BIT) { 722 not_op = INDEX_op_not_i64; 723 have_not = TCG_TARGET_HAS_not_i64; 724 } else { 725 not_op = INDEX_op_not_i32; 726 have_not = TCG_TARGET_HAS_not_i32; 727 } 728 if (!have_not) { 729 break; 730 } 731 s->gen_opc_buf[op_index] = not_op; 732 reset_temp(args[0]); 733 gen_args[0] = args[0]; 734 gen_args[1] = args[i]; 735 args += 3; 736 gen_args += 2; 737 continue; 738 } 739 default: 740 break; 741 } 742 743 /* Simplify expression for "op r, a, const => mov r, a" cases */ 744 switch (op) { 745 CASE_OP_32_64(add): 746 CASE_OP_32_64(sub): 747 CASE_OP_32_64(shl): 748 CASE_OP_32_64(shr): 749 CASE_OP_32_64(sar): 750 CASE_OP_32_64(rotl): 751 CASE_OP_32_64(rotr): 752 CASE_OP_32_64(or): 753 CASE_OP_32_64(xor): 754 CASE_OP_32_64(andc): 755 if (temps[args[1]].state != TCG_TEMP_CONST 756 && temps[args[2]].state == TCG_TEMP_CONST 757 && temps[args[2]].val == 0) { 758 goto do_mov3; 759 } 760 break; 761 CASE_OP_32_64(and): 762 CASE_OP_32_64(orc): 763 CASE_OP_32_64(eqv): 764 if (temps[args[1]].state != TCG_TEMP_CONST 765 && temps[args[2]].state == TCG_TEMP_CONST 766 && temps[args[2]].val == -1) { 767 goto do_mov3; 768 } 769 break; 770 do_mov3: 771 if (temps_are_copies(args[0], args[1])) { 772 s->gen_opc_buf[op_index] = INDEX_op_nop; 773 } else { 774 tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]); 775 gen_args += 2; 776 } 777 args += 3; 778 continue; 779 default: 780 break; 781 } 782 783 /* Simplify using known-zero bits. Currently only ops with a single 784 output argument is supported. */ 785 mask = -1; 786 affected = -1; 787 switch (op) { 788 CASE_OP_32_64(ext8s): 789 if ((temps[args[1]].mask & 0x80) != 0) { 790 break; 791 } 792 CASE_OP_32_64(ext8u): 793 mask = 0xff; 794 goto and_const; 795 CASE_OP_32_64(ext16s): 796 if ((temps[args[1]].mask & 0x8000) != 0) { 797 break; 798 } 799 CASE_OP_32_64(ext16u): 800 mask = 0xffff; 801 goto and_const; 802 case INDEX_op_ext32s_i64: 803 if ((temps[args[1]].mask & 0x80000000) != 0) { 804 break; 805 } 806 case INDEX_op_ext32u_i64: 807 mask = 0xffffffffU; 808 goto and_const; 809 810 CASE_OP_32_64(and): 811 mask = temps[args[2]].mask; 812 if (temps[args[2]].state == TCG_TEMP_CONST) { 813 and_const: 814 affected = temps[args[1]].mask & ~mask; 815 } 816 mask = temps[args[1]].mask & mask; 817 break; 818 819 CASE_OP_32_64(andc): 820 /* Known-zeros does not imply known-ones. Therefore unless 821 args[2] is constant, we can't infer anything from it. */ 822 if (temps[args[2]].state == TCG_TEMP_CONST) { 823 mask = ~temps[args[2]].mask; 824 goto and_const; 825 } 826 /* But we certainly know nothing outside args[1] may be set. */ 827 mask = temps[args[1]].mask; 828 break; 829 830 case INDEX_op_sar_i32: 831 if (temps[args[2]].state == TCG_TEMP_CONST) { 832 tmp = temps[args[2]].val & 31; 833 mask = (int32_t)temps[args[1]].mask >> tmp; 834 } 835 break; 836 case INDEX_op_sar_i64: 837 if (temps[args[2]].state == TCG_TEMP_CONST) { 838 tmp = temps[args[2]].val & 63; 839 mask = (int64_t)temps[args[1]].mask >> tmp; 840 } 841 break; 842 843 case INDEX_op_shr_i32: 844 if (temps[args[2]].state == TCG_TEMP_CONST) { 845 tmp = temps[args[2]].val & 31; 846 mask = (uint32_t)temps[args[1]].mask >> tmp; 847 } 848 break; 849 case INDEX_op_shr_i64: 850 if (temps[args[2]].state == TCG_TEMP_CONST) { 851 tmp = temps[args[2]].val & 63; 852 mask = (uint64_t)temps[args[1]].mask >> tmp; 853 } 854 break; 855 856 case INDEX_op_trunc_shr_i32: 857 mask = (uint64_t)temps[args[1]].mask >> args[2]; 858 break; 859 860 CASE_OP_32_64(shl): 861 if (temps[args[2]].state == TCG_TEMP_CONST) { 862 tmp = temps[args[2]].val & (TCG_TARGET_REG_BITS - 1); 863 mask = temps[args[1]].mask << tmp; 864 } 865 break; 866 867 CASE_OP_32_64(neg): 868 /* Set to 1 all bits to the left of the rightmost. */ 869 mask = -(temps[args[1]].mask & -temps[args[1]].mask); 870 break; 871 872 CASE_OP_32_64(deposit): 873 mask = deposit64(temps[args[1]].mask, args[3], args[4], 874 temps[args[2]].mask); 875 break; 876 877 CASE_OP_32_64(or): 878 CASE_OP_32_64(xor): 879 mask = temps[args[1]].mask | temps[args[2]].mask; 880 break; 881 882 CASE_OP_32_64(setcond): 883 case INDEX_op_setcond2_i32: 884 mask = 1; 885 break; 886 887 CASE_OP_32_64(movcond): 888 mask = temps[args[3]].mask | temps[args[4]].mask; 889 break; 890 891 CASE_OP_32_64(ld8u): 892 mask = 0xff; 893 break; 894 CASE_OP_32_64(ld16u): 895 mask = 0xffff; 896 break; 897 case INDEX_op_ld32u_i64: 898 mask = 0xffffffffu; 899 break; 900 901 CASE_OP_32_64(qemu_ld): 902 { 903 TCGMemOp mop = args[nb_oargs + nb_iargs]; 904 if (!(mop & MO_SIGN)) { 905 mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1; 906 } 907 } 908 break; 909 910 default: 911 break; 912 } 913 914 /* 32-bit ops generate 32-bit results. For the result is zero test 915 below, we can ignore high bits, but for further optimizations we 916 need to record that the high bits contain garbage. */ 917 partmask = mask; 918 if (!(def->flags & TCG_OPF_64BIT)) { 919 mask |= ~(tcg_target_ulong)0xffffffffu; 920 partmask &= 0xffffffffu; 921 affected &= 0xffffffffu; 922 } 923 924 if (partmask == 0) { 925 assert(nb_oargs == 1); 926 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); 927 args += nb_args; 928 gen_args += 2; 929 continue; 930 } 931 if (affected == 0) { 932 assert(nb_oargs == 1); 933 if (temps_are_copies(args[0], args[1])) { 934 s->gen_opc_buf[op_index] = INDEX_op_nop; 935 } else if (temps[args[1]].state != TCG_TEMP_CONST) { 936 tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]); 937 gen_args += 2; 938 } else { 939 tcg_opt_gen_movi(s, op_index, gen_args, op, 940 args[0], temps[args[1]].val); 941 gen_args += 2; 942 } 943 args += nb_args; 944 continue; 945 } 946 947 /* Simplify expression for "op r, a, 0 => movi r, 0" cases */ 948 switch (op) { 949 CASE_OP_32_64(and): 950 CASE_OP_32_64(mul): 951 CASE_OP_32_64(muluh): 952 CASE_OP_32_64(mulsh): 953 if ((temps[args[2]].state == TCG_TEMP_CONST 954 && temps[args[2]].val == 0)) { 955 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); 956 args += 3; 957 gen_args += 2; 958 continue; 959 } 960 break; 961 default: 962 break; 963 } 964 965 /* Simplify expression for "op r, a, a => mov r, a" cases */ 966 switch (op) { 967 CASE_OP_32_64(or): 968 CASE_OP_32_64(and): 969 if (temps_are_copies(args[1], args[2])) { 970 if (temps_are_copies(args[0], args[1])) { 971 s->gen_opc_buf[op_index] = INDEX_op_nop; 972 } else { 973 tcg_opt_gen_mov(s, op_index, gen_args, op, 974 args[0], args[1]); 975 gen_args += 2; 976 } 977 args += 3; 978 continue; 979 } 980 break; 981 default: 982 break; 983 } 984 985 /* Simplify expression for "op r, a, a => movi r, 0" cases */ 986 switch (op) { 987 CASE_OP_32_64(andc): 988 CASE_OP_32_64(sub): 989 CASE_OP_32_64(xor): 990 if (temps_are_copies(args[1], args[2])) { 991 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], 0); 992 gen_args += 2; 993 args += 3; 994 continue; 995 } 996 break; 997 default: 998 break; 999 } 1000 1001 /* Propagate constants through copy operations and do constant 1002 folding. Constants will be substituted to arguments by register 1003 allocator where needed and possible. Also detect copies. */ 1004 switch (op) { 1005 CASE_OP_32_64(mov): 1006 if (temps_are_copies(args[0], args[1])) { 1007 args += 2; 1008 s->gen_opc_buf[op_index] = INDEX_op_nop; 1009 break; 1010 } 1011 if (temps[args[1]].state != TCG_TEMP_CONST) { 1012 tcg_opt_gen_mov(s, op_index, gen_args, op, args[0], args[1]); 1013 gen_args += 2; 1014 args += 2; 1015 break; 1016 } 1017 /* Source argument is constant. Rewrite the operation and 1018 let movi case handle it. */ 1019 args[1] = temps[args[1]].val; 1020 /* fallthrough */ 1021 CASE_OP_32_64(movi): 1022 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], args[1]); 1023 gen_args += 2; 1024 args += 2; 1025 break; 1026 1027 CASE_OP_32_64(not): 1028 CASE_OP_32_64(neg): 1029 CASE_OP_32_64(ext8s): 1030 CASE_OP_32_64(ext8u): 1031 CASE_OP_32_64(ext16s): 1032 CASE_OP_32_64(ext16u): 1033 case INDEX_op_ext32s_i64: 1034 case INDEX_op_ext32u_i64: 1035 if (temps[args[1]].state == TCG_TEMP_CONST) { 1036 tmp = do_constant_folding(op, temps[args[1]].val, 0); 1037 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); 1038 gen_args += 2; 1039 args += 2; 1040 break; 1041 } 1042 goto do_default; 1043 1044 case INDEX_op_trunc_shr_i32: 1045 if (temps[args[1]].state == TCG_TEMP_CONST) { 1046 tmp = do_constant_folding(op, temps[args[1]].val, args[2]); 1047 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); 1048 gen_args += 2; 1049 args += 3; 1050 break; 1051 } 1052 goto do_default; 1053 1054 CASE_OP_32_64(add): 1055 CASE_OP_32_64(sub): 1056 CASE_OP_32_64(mul): 1057 CASE_OP_32_64(or): 1058 CASE_OP_32_64(and): 1059 CASE_OP_32_64(xor): 1060 CASE_OP_32_64(shl): 1061 CASE_OP_32_64(shr): 1062 CASE_OP_32_64(sar): 1063 CASE_OP_32_64(rotl): 1064 CASE_OP_32_64(rotr): 1065 CASE_OP_32_64(andc): 1066 CASE_OP_32_64(orc): 1067 CASE_OP_32_64(eqv): 1068 CASE_OP_32_64(nand): 1069 CASE_OP_32_64(nor): 1070 CASE_OP_32_64(muluh): 1071 CASE_OP_32_64(mulsh): 1072 CASE_OP_32_64(div): 1073 CASE_OP_32_64(divu): 1074 CASE_OP_32_64(rem): 1075 CASE_OP_32_64(remu): 1076 if (temps[args[1]].state == TCG_TEMP_CONST 1077 && temps[args[2]].state == TCG_TEMP_CONST) { 1078 tmp = do_constant_folding(op, temps[args[1]].val, 1079 temps[args[2]].val); 1080 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); 1081 gen_args += 2; 1082 args += 3; 1083 break; 1084 } 1085 goto do_default; 1086 1087 CASE_OP_32_64(deposit): 1088 if (temps[args[1]].state == TCG_TEMP_CONST 1089 && temps[args[2]].state == TCG_TEMP_CONST) { 1090 tmp = deposit64(temps[args[1]].val, args[3], args[4], 1091 temps[args[2]].val); 1092 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); 1093 gen_args += 2; 1094 args += 5; 1095 break; 1096 } 1097 goto do_default; 1098 1099 CASE_OP_32_64(setcond): 1100 tmp = do_constant_folding_cond(op, args[1], args[2], args[3]); 1101 if (tmp != 2) { 1102 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); 1103 gen_args += 2; 1104 args += 4; 1105 break; 1106 } 1107 goto do_default; 1108 1109 CASE_OP_32_64(brcond): 1110 tmp = do_constant_folding_cond(op, args[0], args[1], args[2]); 1111 if (tmp != 2) { 1112 if (tmp) { 1113 reset_all_temps(nb_temps); 1114 s->gen_opc_buf[op_index] = INDEX_op_br; 1115 gen_args[0] = args[3]; 1116 gen_args += 1; 1117 } else { 1118 s->gen_opc_buf[op_index] = INDEX_op_nop; 1119 } 1120 args += 4; 1121 break; 1122 } 1123 goto do_default; 1124 1125 CASE_OP_32_64(movcond): 1126 tmp = do_constant_folding_cond(op, args[1], args[2], args[5]); 1127 if (tmp != 2) { 1128 if (temps_are_copies(args[0], args[4-tmp])) { 1129 s->gen_opc_buf[op_index] = INDEX_op_nop; 1130 } else if (temps[args[4-tmp]].state == TCG_TEMP_CONST) { 1131 tcg_opt_gen_movi(s, op_index, gen_args, op, 1132 args[0], temps[args[4-tmp]].val); 1133 gen_args += 2; 1134 } else { 1135 tcg_opt_gen_mov(s, op_index, gen_args, op, 1136 args[0], args[4-tmp]); 1137 gen_args += 2; 1138 } 1139 args += 6; 1140 break; 1141 } 1142 goto do_default; 1143 1144 case INDEX_op_add2_i32: 1145 case INDEX_op_sub2_i32: 1146 if (temps[args[2]].state == TCG_TEMP_CONST 1147 && temps[args[3]].state == TCG_TEMP_CONST 1148 && temps[args[4]].state == TCG_TEMP_CONST 1149 && temps[args[5]].state == TCG_TEMP_CONST) { 1150 uint32_t al = temps[args[2]].val; 1151 uint32_t ah = temps[args[3]].val; 1152 uint32_t bl = temps[args[4]].val; 1153 uint32_t bh = temps[args[5]].val; 1154 uint64_t a = ((uint64_t)ah << 32) | al; 1155 uint64_t b = ((uint64_t)bh << 32) | bl; 1156 TCGArg rl, rh; 1157 1158 if (op == INDEX_op_add2_i32) { 1159 a += b; 1160 } else { 1161 a -= b; 1162 } 1163 1164 /* We emit the extra nop when we emit the add2/sub2. */ 1165 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop); 1166 1167 rl = args[0]; 1168 rh = args[1]; 1169 tcg_opt_gen_movi(s, op_index, &gen_args[0], 1170 op, rl, (uint32_t)a); 1171 tcg_opt_gen_movi(s, ++op_index, &gen_args[2], 1172 op, rh, (uint32_t)(a >> 32)); 1173 gen_args += 4; 1174 args += 6; 1175 break; 1176 } 1177 goto do_default; 1178 1179 case INDEX_op_mulu2_i32: 1180 if (temps[args[2]].state == TCG_TEMP_CONST 1181 && temps[args[3]].state == TCG_TEMP_CONST) { 1182 uint32_t a = temps[args[2]].val; 1183 uint32_t b = temps[args[3]].val; 1184 uint64_t r = (uint64_t)a * b; 1185 TCGArg rl, rh; 1186 1187 /* We emit the extra nop when we emit the mulu2. */ 1188 assert(s->gen_opc_buf[op_index + 1] == INDEX_op_nop); 1189 1190 rl = args[0]; 1191 rh = args[1]; 1192 tcg_opt_gen_movi(s, op_index, &gen_args[0], 1193 op, rl, (uint32_t)r); 1194 tcg_opt_gen_movi(s, ++op_index, &gen_args[2], 1195 op, rh, (uint32_t)(r >> 32)); 1196 gen_args += 4; 1197 args += 4; 1198 break; 1199 } 1200 goto do_default; 1201 1202 case INDEX_op_brcond2_i32: 1203 tmp = do_constant_folding_cond2(&args[0], &args[2], args[4]); 1204 if (tmp != 2) { 1205 if (tmp) { 1206 do_brcond_true: 1207 reset_all_temps(nb_temps); 1208 s->gen_opc_buf[op_index] = INDEX_op_br; 1209 gen_args[0] = args[5]; 1210 gen_args += 1; 1211 } else { 1212 do_brcond_false: 1213 s->gen_opc_buf[op_index] = INDEX_op_nop; 1214 } 1215 } else if ((args[4] == TCG_COND_LT || args[4] == TCG_COND_GE) 1216 && temps[args[2]].state == TCG_TEMP_CONST 1217 && temps[args[3]].state == TCG_TEMP_CONST 1218 && temps[args[2]].val == 0 1219 && temps[args[3]].val == 0) { 1220 /* Simplify LT/GE comparisons vs zero to a single compare 1221 vs the high word of the input. */ 1222 do_brcond_high: 1223 reset_all_temps(nb_temps); 1224 s->gen_opc_buf[op_index] = INDEX_op_brcond_i32; 1225 gen_args[0] = args[1]; 1226 gen_args[1] = args[3]; 1227 gen_args[2] = args[4]; 1228 gen_args[3] = args[5]; 1229 gen_args += 4; 1230 } else if (args[4] == TCG_COND_EQ) { 1231 /* Simplify EQ comparisons where one of the pairs 1232 can be simplified. */ 1233 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1234 args[0], args[2], TCG_COND_EQ); 1235 if (tmp == 0) { 1236 goto do_brcond_false; 1237 } else if (tmp == 1) { 1238 goto do_brcond_high; 1239 } 1240 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1241 args[1], args[3], TCG_COND_EQ); 1242 if (tmp == 0) { 1243 goto do_brcond_false; 1244 } else if (tmp != 1) { 1245 goto do_default; 1246 } 1247 do_brcond_low: 1248 reset_all_temps(nb_temps); 1249 s->gen_opc_buf[op_index] = INDEX_op_brcond_i32; 1250 gen_args[0] = args[0]; 1251 gen_args[1] = args[2]; 1252 gen_args[2] = args[4]; 1253 gen_args[3] = args[5]; 1254 gen_args += 4; 1255 } else if (args[4] == TCG_COND_NE) { 1256 /* Simplify NE comparisons where one of the pairs 1257 can be simplified. */ 1258 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1259 args[0], args[2], TCG_COND_NE); 1260 if (tmp == 0) { 1261 goto do_brcond_high; 1262 } else if (tmp == 1) { 1263 goto do_brcond_true; 1264 } 1265 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1266 args[1], args[3], TCG_COND_NE); 1267 if (tmp == 0) { 1268 goto do_brcond_low; 1269 } else if (tmp == 1) { 1270 goto do_brcond_true; 1271 } 1272 goto do_default; 1273 } else { 1274 goto do_default; 1275 } 1276 args += 6; 1277 break; 1278 1279 case INDEX_op_setcond2_i32: 1280 tmp = do_constant_folding_cond2(&args[1], &args[3], args[5]); 1281 if (tmp != 2) { 1282 do_setcond_const: 1283 tcg_opt_gen_movi(s, op_index, gen_args, op, args[0], tmp); 1284 gen_args += 2; 1285 } else if ((args[5] == TCG_COND_LT || args[5] == TCG_COND_GE) 1286 && temps[args[3]].state == TCG_TEMP_CONST 1287 && temps[args[4]].state == TCG_TEMP_CONST 1288 && temps[args[3]].val == 0 1289 && temps[args[4]].val == 0) { 1290 /* Simplify LT/GE comparisons vs zero to a single compare 1291 vs the high word of the input. */ 1292 do_setcond_high: 1293 s->gen_opc_buf[op_index] = INDEX_op_setcond_i32; 1294 reset_temp(args[0]); 1295 temps[args[0]].mask = 1; 1296 gen_args[0] = args[0]; 1297 gen_args[1] = args[2]; 1298 gen_args[2] = args[4]; 1299 gen_args[3] = args[5]; 1300 gen_args += 4; 1301 } else if (args[5] == TCG_COND_EQ) { 1302 /* Simplify EQ comparisons where one of the pairs 1303 can be simplified. */ 1304 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1305 args[1], args[3], TCG_COND_EQ); 1306 if (tmp == 0) { 1307 goto do_setcond_const; 1308 } else if (tmp == 1) { 1309 goto do_setcond_high; 1310 } 1311 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1312 args[2], args[4], TCG_COND_EQ); 1313 if (tmp == 0) { 1314 goto do_setcond_high; 1315 } else if (tmp != 1) { 1316 goto do_default; 1317 } 1318 do_setcond_low: 1319 reset_temp(args[0]); 1320 temps[args[0]].mask = 1; 1321 s->gen_opc_buf[op_index] = INDEX_op_setcond_i32; 1322 gen_args[0] = args[0]; 1323 gen_args[1] = args[1]; 1324 gen_args[2] = args[3]; 1325 gen_args[3] = args[5]; 1326 gen_args += 4; 1327 } else if (args[5] == TCG_COND_NE) { 1328 /* Simplify NE comparisons where one of the pairs 1329 can be simplified. */ 1330 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1331 args[1], args[3], TCG_COND_NE); 1332 if (tmp == 0) { 1333 goto do_setcond_high; 1334 } else if (tmp == 1) { 1335 goto do_setcond_const; 1336 } 1337 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1338 args[2], args[4], TCG_COND_NE); 1339 if (tmp == 0) { 1340 goto do_setcond_low; 1341 } else if (tmp == 1) { 1342 goto do_setcond_const; 1343 } 1344 goto do_default; 1345 } else { 1346 goto do_default; 1347 } 1348 args += 6; 1349 break; 1350 1351 case INDEX_op_call: 1352 if (!(args[nb_oargs + nb_iargs + 1] 1353 & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) { 1354 for (i = 0; i < nb_globals; i++) { 1355 reset_temp(i); 1356 } 1357 } 1358 goto do_reset_output; 1359 1360 default: 1361 do_default: 1362 /* Default case: we know nothing about operation (or were unable 1363 to compute the operation result) so no propagation is done. 1364 We trash everything if the operation is the end of a basic 1365 block, otherwise we only trash the output args. "mask" is 1366 the non-zero bits mask for the first output arg. */ 1367 if (def->flags & TCG_OPF_BB_END) { 1368 reset_all_temps(nb_temps); 1369 } else { 1370 do_reset_output: 1371 for (i = 0; i < nb_oargs; i++) { 1372 reset_temp(args[i]); 1373 /* Save the corresponding known-zero bits mask for the 1374 first output argument (only one supported so far). */ 1375 if (i == 0) { 1376 temps[args[i]].mask = mask; 1377 } 1378 } 1379 } 1380 for (i = 0; i < nb_args; i++) { 1381 gen_args[i] = args[i]; 1382 } 1383 args += nb_args; 1384 gen_args += nb_args; 1385 break; 1386 } 1387 } 1388 1389 return gen_args; 1390 } 1391 1392 TCGArg *tcg_optimize(TCGContext *s, uint16_t *tcg_opc_ptr, 1393 TCGArg *args, TCGOpDef *tcg_op_defs) 1394 { 1395 TCGArg *res; 1396 res = tcg_constant_folding(s, tcg_opc_ptr, args, tcg_op_defs); 1397 return res; 1398 } 1399