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 "qemu/osdep.h" 27 #include "tcg/tcg-op.h" 28 29 #define CASE_OP_32_64(x) \ 30 glue(glue(case INDEX_op_, x), _i32): \ 31 glue(glue(case INDEX_op_, x), _i64) 32 33 #define CASE_OP_32_64_VEC(x) \ 34 glue(glue(case INDEX_op_, x), _i32): \ 35 glue(glue(case INDEX_op_, x), _i64): \ 36 glue(glue(case INDEX_op_, x), _vec) 37 38 struct tcg_temp_info { 39 bool is_const; 40 TCGTemp *prev_copy; 41 TCGTemp *next_copy; 42 tcg_target_ulong val; 43 tcg_target_ulong mask; 44 }; 45 46 static inline struct tcg_temp_info *ts_info(TCGTemp *ts) 47 { 48 return ts->state_ptr; 49 } 50 51 static inline struct tcg_temp_info *arg_info(TCGArg arg) 52 { 53 return ts_info(arg_temp(arg)); 54 } 55 56 static inline bool ts_is_const(TCGTemp *ts) 57 { 58 return ts_info(ts)->is_const; 59 } 60 61 static inline bool arg_is_const(TCGArg arg) 62 { 63 return ts_is_const(arg_temp(arg)); 64 } 65 66 static inline bool ts_is_copy(TCGTemp *ts) 67 { 68 return ts_info(ts)->next_copy != ts; 69 } 70 71 /* Reset TEMP's state, possibly removing the temp for the list of copies. */ 72 static void reset_ts(TCGTemp *ts) 73 { 74 struct tcg_temp_info *ti = ts_info(ts); 75 struct tcg_temp_info *pi = ts_info(ti->prev_copy); 76 struct tcg_temp_info *ni = ts_info(ti->next_copy); 77 78 ni->prev_copy = ti->prev_copy; 79 pi->next_copy = ti->next_copy; 80 ti->next_copy = ts; 81 ti->prev_copy = ts; 82 ti->is_const = false; 83 ti->mask = -1; 84 } 85 86 static void reset_temp(TCGArg arg) 87 { 88 reset_ts(arg_temp(arg)); 89 } 90 91 /* Initialize and activate a temporary. */ 92 static void init_ts_info(struct tcg_temp_info *infos, 93 TCGTempSet *temps_used, TCGTemp *ts) 94 { 95 size_t idx = temp_idx(ts); 96 if (!test_bit(idx, temps_used->l)) { 97 struct tcg_temp_info *ti = &infos[idx]; 98 99 ts->state_ptr = ti; 100 ti->next_copy = ts; 101 ti->prev_copy = ts; 102 ti->is_const = false; 103 ti->mask = -1; 104 set_bit(idx, temps_used->l); 105 } 106 } 107 108 static void init_arg_info(struct tcg_temp_info *infos, 109 TCGTempSet *temps_used, TCGArg arg) 110 { 111 init_ts_info(infos, temps_used, arg_temp(arg)); 112 } 113 114 static TCGTemp *find_better_copy(TCGContext *s, TCGTemp *ts) 115 { 116 TCGTemp *i; 117 118 /* If this is already a global, we can't do better. */ 119 if (ts->temp_global) { 120 return ts; 121 } 122 123 /* Search for a global first. */ 124 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) { 125 if (i->temp_global) { 126 return i; 127 } 128 } 129 130 /* If it is a temp, search for a temp local. */ 131 if (!ts->temp_local) { 132 for (i = ts_info(ts)->next_copy; i != ts; i = ts_info(i)->next_copy) { 133 if (ts->temp_local) { 134 return i; 135 } 136 } 137 } 138 139 /* Failure to find a better representation, return the same temp. */ 140 return ts; 141 } 142 143 static bool ts_are_copies(TCGTemp *ts1, TCGTemp *ts2) 144 { 145 TCGTemp *i; 146 147 if (ts1 == ts2) { 148 return true; 149 } 150 151 if (!ts_is_copy(ts1) || !ts_is_copy(ts2)) { 152 return false; 153 } 154 155 for (i = ts_info(ts1)->next_copy; i != ts1; i = ts_info(i)->next_copy) { 156 if (i == ts2) { 157 return true; 158 } 159 } 160 161 return false; 162 } 163 164 static bool args_are_copies(TCGArg arg1, TCGArg arg2) 165 { 166 return ts_are_copies(arg_temp(arg1), arg_temp(arg2)); 167 } 168 169 static void tcg_opt_gen_movi(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg val) 170 { 171 const TCGOpDef *def; 172 TCGOpcode new_op; 173 tcg_target_ulong mask; 174 struct tcg_temp_info *di = arg_info(dst); 175 176 def = &tcg_op_defs[op->opc]; 177 if (def->flags & TCG_OPF_VECTOR) { 178 new_op = INDEX_op_dupi_vec; 179 } else if (def->flags & TCG_OPF_64BIT) { 180 new_op = INDEX_op_movi_i64; 181 } else { 182 new_op = INDEX_op_movi_i32; 183 } 184 op->opc = new_op; 185 /* TCGOP_VECL and TCGOP_VECE remain unchanged. */ 186 op->args[0] = dst; 187 op->args[1] = val; 188 189 reset_temp(dst); 190 di->is_const = true; 191 di->val = val; 192 mask = val; 193 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_movi_i32) { 194 /* High bits of the destination are now garbage. */ 195 mask |= ~0xffffffffull; 196 } 197 di->mask = mask; 198 } 199 200 static void tcg_opt_gen_mov(TCGContext *s, TCGOp *op, TCGArg dst, TCGArg src) 201 { 202 TCGTemp *dst_ts = arg_temp(dst); 203 TCGTemp *src_ts = arg_temp(src); 204 const TCGOpDef *def; 205 struct tcg_temp_info *di; 206 struct tcg_temp_info *si; 207 tcg_target_ulong mask; 208 TCGOpcode new_op; 209 210 if (ts_are_copies(dst_ts, src_ts)) { 211 tcg_op_remove(s, op); 212 return; 213 } 214 215 reset_ts(dst_ts); 216 di = ts_info(dst_ts); 217 si = ts_info(src_ts); 218 def = &tcg_op_defs[op->opc]; 219 if (def->flags & TCG_OPF_VECTOR) { 220 new_op = INDEX_op_mov_vec; 221 } else if (def->flags & TCG_OPF_64BIT) { 222 new_op = INDEX_op_mov_i64; 223 } else { 224 new_op = INDEX_op_mov_i32; 225 } 226 op->opc = new_op; 227 /* TCGOP_VECL and TCGOP_VECE remain unchanged. */ 228 op->args[0] = dst; 229 op->args[1] = src; 230 231 mask = si->mask; 232 if (TCG_TARGET_REG_BITS > 32 && new_op == INDEX_op_mov_i32) { 233 /* High bits of the destination are now garbage. */ 234 mask |= ~0xffffffffull; 235 } 236 di->mask = mask; 237 238 if (src_ts->type == dst_ts->type) { 239 struct tcg_temp_info *ni = ts_info(si->next_copy); 240 241 di->next_copy = si->next_copy; 242 di->prev_copy = src_ts; 243 ni->prev_copy = dst_ts; 244 si->next_copy = dst_ts; 245 di->is_const = si->is_const; 246 di->val = si->val; 247 } 248 } 249 250 static TCGArg do_constant_folding_2(TCGOpcode op, TCGArg x, TCGArg y) 251 { 252 uint64_t l64, h64; 253 254 switch (op) { 255 CASE_OP_32_64(add): 256 return x + y; 257 258 CASE_OP_32_64(sub): 259 return x - y; 260 261 CASE_OP_32_64(mul): 262 return x * y; 263 264 CASE_OP_32_64(and): 265 return x & y; 266 267 CASE_OP_32_64(or): 268 return x | y; 269 270 CASE_OP_32_64(xor): 271 return x ^ y; 272 273 case INDEX_op_shl_i32: 274 return (uint32_t)x << (y & 31); 275 276 case INDEX_op_shl_i64: 277 return (uint64_t)x << (y & 63); 278 279 case INDEX_op_shr_i32: 280 return (uint32_t)x >> (y & 31); 281 282 case INDEX_op_shr_i64: 283 return (uint64_t)x >> (y & 63); 284 285 case INDEX_op_sar_i32: 286 return (int32_t)x >> (y & 31); 287 288 case INDEX_op_sar_i64: 289 return (int64_t)x >> (y & 63); 290 291 case INDEX_op_rotr_i32: 292 return ror32(x, y & 31); 293 294 case INDEX_op_rotr_i64: 295 return ror64(x, y & 63); 296 297 case INDEX_op_rotl_i32: 298 return rol32(x, y & 31); 299 300 case INDEX_op_rotl_i64: 301 return rol64(x, y & 63); 302 303 CASE_OP_32_64(not): 304 return ~x; 305 306 CASE_OP_32_64(neg): 307 return -x; 308 309 CASE_OP_32_64(andc): 310 return x & ~y; 311 312 CASE_OP_32_64(orc): 313 return x | ~y; 314 315 CASE_OP_32_64(eqv): 316 return ~(x ^ y); 317 318 CASE_OP_32_64(nand): 319 return ~(x & y); 320 321 CASE_OP_32_64(nor): 322 return ~(x | y); 323 324 case INDEX_op_clz_i32: 325 return (uint32_t)x ? clz32(x) : y; 326 327 case INDEX_op_clz_i64: 328 return x ? clz64(x) : y; 329 330 case INDEX_op_ctz_i32: 331 return (uint32_t)x ? ctz32(x) : y; 332 333 case INDEX_op_ctz_i64: 334 return x ? ctz64(x) : y; 335 336 case INDEX_op_ctpop_i32: 337 return ctpop32(x); 338 339 case INDEX_op_ctpop_i64: 340 return ctpop64(x); 341 342 CASE_OP_32_64(ext8s): 343 return (int8_t)x; 344 345 CASE_OP_32_64(ext16s): 346 return (int16_t)x; 347 348 CASE_OP_32_64(ext8u): 349 return (uint8_t)x; 350 351 CASE_OP_32_64(ext16u): 352 return (uint16_t)x; 353 354 CASE_OP_32_64(bswap16): 355 return bswap16(x); 356 357 CASE_OP_32_64(bswap32): 358 return bswap32(x); 359 360 case INDEX_op_bswap64_i64: 361 return bswap64(x); 362 363 case INDEX_op_ext_i32_i64: 364 case INDEX_op_ext32s_i64: 365 return (int32_t)x; 366 367 case INDEX_op_extu_i32_i64: 368 case INDEX_op_extrl_i64_i32: 369 case INDEX_op_ext32u_i64: 370 return (uint32_t)x; 371 372 case INDEX_op_extrh_i64_i32: 373 return (uint64_t)x >> 32; 374 375 case INDEX_op_muluh_i32: 376 return ((uint64_t)(uint32_t)x * (uint32_t)y) >> 32; 377 case INDEX_op_mulsh_i32: 378 return ((int64_t)(int32_t)x * (int32_t)y) >> 32; 379 380 case INDEX_op_muluh_i64: 381 mulu64(&l64, &h64, x, y); 382 return h64; 383 case INDEX_op_mulsh_i64: 384 muls64(&l64, &h64, x, y); 385 return h64; 386 387 case INDEX_op_div_i32: 388 /* Avoid crashing on divide by zero, otherwise undefined. */ 389 return (int32_t)x / ((int32_t)y ? : 1); 390 case INDEX_op_divu_i32: 391 return (uint32_t)x / ((uint32_t)y ? : 1); 392 case INDEX_op_div_i64: 393 return (int64_t)x / ((int64_t)y ? : 1); 394 case INDEX_op_divu_i64: 395 return (uint64_t)x / ((uint64_t)y ? : 1); 396 397 case INDEX_op_rem_i32: 398 return (int32_t)x % ((int32_t)y ? : 1); 399 case INDEX_op_remu_i32: 400 return (uint32_t)x % ((uint32_t)y ? : 1); 401 case INDEX_op_rem_i64: 402 return (int64_t)x % ((int64_t)y ? : 1); 403 case INDEX_op_remu_i64: 404 return (uint64_t)x % ((uint64_t)y ? : 1); 405 406 default: 407 fprintf(stderr, 408 "Unrecognized operation %d in do_constant_folding.\n", op); 409 tcg_abort(); 410 } 411 } 412 413 static TCGArg do_constant_folding(TCGOpcode op, TCGArg x, TCGArg y) 414 { 415 const TCGOpDef *def = &tcg_op_defs[op]; 416 TCGArg res = do_constant_folding_2(op, x, y); 417 if (!(def->flags & TCG_OPF_64BIT)) { 418 res = (int32_t)res; 419 } 420 return res; 421 } 422 423 static bool do_constant_folding_cond_32(uint32_t x, uint32_t y, TCGCond c) 424 { 425 switch (c) { 426 case TCG_COND_EQ: 427 return x == y; 428 case TCG_COND_NE: 429 return x != y; 430 case TCG_COND_LT: 431 return (int32_t)x < (int32_t)y; 432 case TCG_COND_GE: 433 return (int32_t)x >= (int32_t)y; 434 case TCG_COND_LE: 435 return (int32_t)x <= (int32_t)y; 436 case TCG_COND_GT: 437 return (int32_t)x > (int32_t)y; 438 case TCG_COND_LTU: 439 return x < y; 440 case TCG_COND_GEU: 441 return x >= y; 442 case TCG_COND_LEU: 443 return x <= y; 444 case TCG_COND_GTU: 445 return x > y; 446 default: 447 tcg_abort(); 448 } 449 } 450 451 static bool do_constant_folding_cond_64(uint64_t x, uint64_t y, TCGCond c) 452 { 453 switch (c) { 454 case TCG_COND_EQ: 455 return x == y; 456 case TCG_COND_NE: 457 return x != y; 458 case TCG_COND_LT: 459 return (int64_t)x < (int64_t)y; 460 case TCG_COND_GE: 461 return (int64_t)x >= (int64_t)y; 462 case TCG_COND_LE: 463 return (int64_t)x <= (int64_t)y; 464 case TCG_COND_GT: 465 return (int64_t)x > (int64_t)y; 466 case TCG_COND_LTU: 467 return x < y; 468 case TCG_COND_GEU: 469 return x >= y; 470 case TCG_COND_LEU: 471 return x <= y; 472 case TCG_COND_GTU: 473 return x > y; 474 default: 475 tcg_abort(); 476 } 477 } 478 479 static bool do_constant_folding_cond_eq(TCGCond c) 480 { 481 switch (c) { 482 case TCG_COND_GT: 483 case TCG_COND_LTU: 484 case TCG_COND_LT: 485 case TCG_COND_GTU: 486 case TCG_COND_NE: 487 return 0; 488 case TCG_COND_GE: 489 case TCG_COND_GEU: 490 case TCG_COND_LE: 491 case TCG_COND_LEU: 492 case TCG_COND_EQ: 493 return 1; 494 default: 495 tcg_abort(); 496 } 497 } 498 499 /* Return 2 if the condition can't be simplified, and the result 500 of the condition (0 or 1) if it can */ 501 static TCGArg do_constant_folding_cond(TCGOpcode op, TCGArg x, 502 TCGArg y, TCGCond c) 503 { 504 tcg_target_ulong xv = arg_info(x)->val; 505 tcg_target_ulong yv = arg_info(y)->val; 506 if (arg_is_const(x) && arg_is_const(y)) { 507 const TCGOpDef *def = &tcg_op_defs[op]; 508 tcg_debug_assert(!(def->flags & TCG_OPF_VECTOR)); 509 if (def->flags & TCG_OPF_64BIT) { 510 return do_constant_folding_cond_64(xv, yv, c); 511 } else { 512 return do_constant_folding_cond_32(xv, yv, c); 513 } 514 } else if (args_are_copies(x, y)) { 515 return do_constant_folding_cond_eq(c); 516 } else if (arg_is_const(y) && yv == 0) { 517 switch (c) { 518 case TCG_COND_LTU: 519 return 0; 520 case TCG_COND_GEU: 521 return 1; 522 default: 523 return 2; 524 } 525 } 526 return 2; 527 } 528 529 /* Return 2 if the condition can't be simplified, and the result 530 of the condition (0 or 1) if it can */ 531 static TCGArg do_constant_folding_cond2(TCGArg *p1, TCGArg *p2, TCGCond c) 532 { 533 TCGArg al = p1[0], ah = p1[1]; 534 TCGArg bl = p2[0], bh = p2[1]; 535 536 if (arg_is_const(bl) && arg_is_const(bh)) { 537 tcg_target_ulong blv = arg_info(bl)->val; 538 tcg_target_ulong bhv = arg_info(bh)->val; 539 uint64_t b = deposit64(blv, 32, 32, bhv); 540 541 if (arg_is_const(al) && arg_is_const(ah)) { 542 tcg_target_ulong alv = arg_info(al)->val; 543 tcg_target_ulong ahv = arg_info(ah)->val; 544 uint64_t a = deposit64(alv, 32, 32, ahv); 545 return do_constant_folding_cond_64(a, b, c); 546 } 547 if (b == 0) { 548 switch (c) { 549 case TCG_COND_LTU: 550 return 0; 551 case TCG_COND_GEU: 552 return 1; 553 default: 554 break; 555 } 556 } 557 } 558 if (args_are_copies(al, bl) && args_are_copies(ah, bh)) { 559 return do_constant_folding_cond_eq(c); 560 } 561 return 2; 562 } 563 564 static bool swap_commutative(TCGArg dest, TCGArg *p1, TCGArg *p2) 565 { 566 TCGArg a1 = *p1, a2 = *p2; 567 int sum = 0; 568 sum += arg_is_const(a1); 569 sum -= arg_is_const(a2); 570 571 /* Prefer the constant in second argument, and then the form 572 op a, a, b, which is better handled on non-RISC hosts. */ 573 if (sum > 0 || (sum == 0 && dest == a2)) { 574 *p1 = a2; 575 *p2 = a1; 576 return true; 577 } 578 return false; 579 } 580 581 static bool swap_commutative2(TCGArg *p1, TCGArg *p2) 582 { 583 int sum = 0; 584 sum += arg_is_const(p1[0]); 585 sum += arg_is_const(p1[1]); 586 sum -= arg_is_const(p2[0]); 587 sum -= arg_is_const(p2[1]); 588 if (sum > 0) { 589 TCGArg t; 590 t = p1[0], p1[0] = p2[0], p2[0] = t; 591 t = p1[1], p1[1] = p2[1], p2[1] = t; 592 return true; 593 } 594 return false; 595 } 596 597 /* Propagate constants and copies, fold constant expressions. */ 598 void tcg_optimize(TCGContext *s) 599 { 600 int nb_temps, nb_globals; 601 TCGOp *op, *op_next, *prev_mb = NULL; 602 struct tcg_temp_info *infos; 603 TCGTempSet temps_used; 604 605 /* Array VALS has an element for each temp. 606 If this temp holds a constant then its value is kept in VALS' element. 607 If this temp is a copy of other ones then the other copies are 608 available through the doubly linked circular list. */ 609 610 nb_temps = s->nb_temps; 611 nb_globals = s->nb_globals; 612 bitmap_zero(temps_used.l, nb_temps); 613 infos = tcg_malloc(sizeof(struct tcg_temp_info) * nb_temps); 614 615 QTAILQ_FOREACH_SAFE(op, &s->ops, link, op_next) { 616 tcg_target_ulong mask, partmask, affected; 617 int nb_oargs, nb_iargs, i; 618 TCGArg tmp; 619 TCGOpcode opc = op->opc; 620 const TCGOpDef *def = &tcg_op_defs[opc]; 621 622 /* Count the arguments, and initialize the temps that are 623 going to be used */ 624 if (opc == INDEX_op_call) { 625 nb_oargs = TCGOP_CALLO(op); 626 nb_iargs = TCGOP_CALLI(op); 627 for (i = 0; i < nb_oargs + nb_iargs; i++) { 628 TCGTemp *ts = arg_temp(op->args[i]); 629 if (ts) { 630 init_ts_info(infos, &temps_used, ts); 631 } 632 } 633 } else { 634 nb_oargs = def->nb_oargs; 635 nb_iargs = def->nb_iargs; 636 for (i = 0; i < nb_oargs + nb_iargs; i++) { 637 init_arg_info(infos, &temps_used, op->args[i]); 638 } 639 } 640 641 /* Do copy propagation */ 642 for (i = nb_oargs; i < nb_oargs + nb_iargs; i++) { 643 TCGTemp *ts = arg_temp(op->args[i]); 644 if (ts && ts_is_copy(ts)) { 645 op->args[i] = temp_arg(find_better_copy(s, ts)); 646 } 647 } 648 649 /* For commutative operations make constant second argument */ 650 switch (opc) { 651 CASE_OP_32_64_VEC(add): 652 CASE_OP_32_64_VEC(mul): 653 CASE_OP_32_64_VEC(and): 654 CASE_OP_32_64_VEC(or): 655 CASE_OP_32_64_VEC(xor): 656 CASE_OP_32_64(eqv): 657 CASE_OP_32_64(nand): 658 CASE_OP_32_64(nor): 659 CASE_OP_32_64(muluh): 660 CASE_OP_32_64(mulsh): 661 swap_commutative(op->args[0], &op->args[1], &op->args[2]); 662 break; 663 CASE_OP_32_64(brcond): 664 if (swap_commutative(-1, &op->args[0], &op->args[1])) { 665 op->args[2] = tcg_swap_cond(op->args[2]); 666 } 667 break; 668 CASE_OP_32_64(setcond): 669 if (swap_commutative(op->args[0], &op->args[1], &op->args[2])) { 670 op->args[3] = tcg_swap_cond(op->args[3]); 671 } 672 break; 673 CASE_OP_32_64(movcond): 674 if (swap_commutative(-1, &op->args[1], &op->args[2])) { 675 op->args[5] = tcg_swap_cond(op->args[5]); 676 } 677 /* For movcond, we canonicalize the "false" input reg to match 678 the destination reg so that the tcg backend can implement 679 a "move if true" operation. */ 680 if (swap_commutative(op->args[0], &op->args[4], &op->args[3])) { 681 op->args[5] = tcg_invert_cond(op->args[5]); 682 } 683 break; 684 CASE_OP_32_64(add2): 685 swap_commutative(op->args[0], &op->args[2], &op->args[4]); 686 swap_commutative(op->args[1], &op->args[3], &op->args[5]); 687 break; 688 CASE_OP_32_64(mulu2): 689 CASE_OP_32_64(muls2): 690 swap_commutative(op->args[0], &op->args[2], &op->args[3]); 691 break; 692 case INDEX_op_brcond2_i32: 693 if (swap_commutative2(&op->args[0], &op->args[2])) { 694 op->args[4] = tcg_swap_cond(op->args[4]); 695 } 696 break; 697 case INDEX_op_setcond2_i32: 698 if (swap_commutative2(&op->args[1], &op->args[3])) { 699 op->args[5] = tcg_swap_cond(op->args[5]); 700 } 701 break; 702 default: 703 break; 704 } 705 706 /* Simplify expressions for "shift/rot r, 0, a => movi r, 0", 707 and "sub r, 0, a => neg r, a" case. */ 708 switch (opc) { 709 CASE_OP_32_64(shl): 710 CASE_OP_32_64(shr): 711 CASE_OP_32_64(sar): 712 CASE_OP_32_64(rotl): 713 CASE_OP_32_64(rotr): 714 if (arg_is_const(op->args[1]) 715 && arg_info(op->args[1])->val == 0) { 716 tcg_opt_gen_movi(s, op, op->args[0], 0); 717 continue; 718 } 719 break; 720 CASE_OP_32_64_VEC(sub): 721 { 722 TCGOpcode neg_op; 723 bool have_neg; 724 725 if (arg_is_const(op->args[2])) { 726 /* Proceed with possible constant folding. */ 727 break; 728 } 729 if (opc == INDEX_op_sub_i32) { 730 neg_op = INDEX_op_neg_i32; 731 have_neg = TCG_TARGET_HAS_neg_i32; 732 } else if (opc == INDEX_op_sub_i64) { 733 neg_op = INDEX_op_neg_i64; 734 have_neg = TCG_TARGET_HAS_neg_i64; 735 } else if (TCG_TARGET_HAS_neg_vec) { 736 TCGType type = TCGOP_VECL(op) + TCG_TYPE_V64; 737 unsigned vece = TCGOP_VECE(op); 738 neg_op = INDEX_op_neg_vec; 739 have_neg = tcg_can_emit_vec_op(neg_op, type, vece) > 0; 740 } else { 741 break; 742 } 743 if (!have_neg) { 744 break; 745 } 746 if (arg_is_const(op->args[1]) 747 && arg_info(op->args[1])->val == 0) { 748 op->opc = neg_op; 749 reset_temp(op->args[0]); 750 op->args[1] = op->args[2]; 751 continue; 752 } 753 } 754 break; 755 CASE_OP_32_64_VEC(xor): 756 CASE_OP_32_64(nand): 757 if (!arg_is_const(op->args[1]) 758 && arg_is_const(op->args[2]) 759 && arg_info(op->args[2])->val == -1) { 760 i = 1; 761 goto try_not; 762 } 763 break; 764 CASE_OP_32_64(nor): 765 if (!arg_is_const(op->args[1]) 766 && arg_is_const(op->args[2]) 767 && arg_info(op->args[2])->val == 0) { 768 i = 1; 769 goto try_not; 770 } 771 break; 772 CASE_OP_32_64_VEC(andc): 773 if (!arg_is_const(op->args[2]) 774 && arg_is_const(op->args[1]) 775 && arg_info(op->args[1])->val == -1) { 776 i = 2; 777 goto try_not; 778 } 779 break; 780 CASE_OP_32_64_VEC(orc): 781 CASE_OP_32_64(eqv): 782 if (!arg_is_const(op->args[2]) 783 && arg_is_const(op->args[1]) 784 && arg_info(op->args[1])->val == 0) { 785 i = 2; 786 goto try_not; 787 } 788 break; 789 try_not: 790 { 791 TCGOpcode not_op; 792 bool have_not; 793 794 if (def->flags & TCG_OPF_VECTOR) { 795 not_op = INDEX_op_not_vec; 796 have_not = TCG_TARGET_HAS_not_vec; 797 } else if (def->flags & TCG_OPF_64BIT) { 798 not_op = INDEX_op_not_i64; 799 have_not = TCG_TARGET_HAS_not_i64; 800 } else { 801 not_op = INDEX_op_not_i32; 802 have_not = TCG_TARGET_HAS_not_i32; 803 } 804 if (!have_not) { 805 break; 806 } 807 op->opc = not_op; 808 reset_temp(op->args[0]); 809 op->args[1] = op->args[i]; 810 continue; 811 } 812 default: 813 break; 814 } 815 816 /* Simplify expression for "op r, a, const => mov r, a" cases */ 817 switch (opc) { 818 CASE_OP_32_64_VEC(add): 819 CASE_OP_32_64_VEC(sub): 820 CASE_OP_32_64_VEC(or): 821 CASE_OP_32_64_VEC(xor): 822 CASE_OP_32_64_VEC(andc): 823 CASE_OP_32_64(shl): 824 CASE_OP_32_64(shr): 825 CASE_OP_32_64(sar): 826 CASE_OP_32_64(rotl): 827 CASE_OP_32_64(rotr): 828 if (!arg_is_const(op->args[1]) 829 && arg_is_const(op->args[2]) 830 && arg_info(op->args[2])->val == 0) { 831 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]); 832 continue; 833 } 834 break; 835 CASE_OP_32_64_VEC(and): 836 CASE_OP_32_64_VEC(orc): 837 CASE_OP_32_64(eqv): 838 if (!arg_is_const(op->args[1]) 839 && arg_is_const(op->args[2]) 840 && arg_info(op->args[2])->val == -1) { 841 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]); 842 continue; 843 } 844 break; 845 default: 846 break; 847 } 848 849 /* Simplify using known-zero bits. Currently only ops with a single 850 output argument is supported. */ 851 mask = -1; 852 affected = -1; 853 switch (opc) { 854 CASE_OP_32_64(ext8s): 855 if ((arg_info(op->args[1])->mask & 0x80) != 0) { 856 break; 857 } 858 QEMU_FALLTHROUGH; 859 CASE_OP_32_64(ext8u): 860 mask = 0xff; 861 goto and_const; 862 CASE_OP_32_64(ext16s): 863 if ((arg_info(op->args[1])->mask & 0x8000) != 0) { 864 break; 865 } 866 QEMU_FALLTHROUGH; 867 CASE_OP_32_64(ext16u): 868 mask = 0xffff; 869 goto and_const; 870 case INDEX_op_ext32s_i64: 871 if ((arg_info(op->args[1])->mask & 0x80000000) != 0) { 872 break; 873 } 874 QEMU_FALLTHROUGH; 875 case INDEX_op_ext32u_i64: 876 mask = 0xffffffffU; 877 goto and_const; 878 879 CASE_OP_32_64(and): 880 mask = arg_info(op->args[2])->mask; 881 if (arg_is_const(op->args[2])) { 882 and_const: 883 affected = arg_info(op->args[1])->mask & ~mask; 884 } 885 mask = arg_info(op->args[1])->mask & mask; 886 break; 887 888 case INDEX_op_ext_i32_i64: 889 if ((arg_info(op->args[1])->mask & 0x80000000) != 0) { 890 break; 891 } 892 QEMU_FALLTHROUGH; 893 case INDEX_op_extu_i32_i64: 894 /* We do not compute affected as it is a size changing op. */ 895 mask = (uint32_t)arg_info(op->args[1])->mask; 896 break; 897 898 CASE_OP_32_64(andc): 899 /* Known-zeros does not imply known-ones. Therefore unless 900 op->args[2] is constant, we can't infer anything from it. */ 901 if (arg_is_const(op->args[2])) { 902 mask = ~arg_info(op->args[2])->mask; 903 goto and_const; 904 } 905 /* But we certainly know nothing outside args[1] may be set. */ 906 mask = arg_info(op->args[1])->mask; 907 break; 908 909 case INDEX_op_sar_i32: 910 if (arg_is_const(op->args[2])) { 911 tmp = arg_info(op->args[2])->val & 31; 912 mask = (int32_t)arg_info(op->args[1])->mask >> tmp; 913 } 914 break; 915 case INDEX_op_sar_i64: 916 if (arg_is_const(op->args[2])) { 917 tmp = arg_info(op->args[2])->val & 63; 918 mask = (int64_t)arg_info(op->args[1])->mask >> tmp; 919 } 920 break; 921 922 case INDEX_op_shr_i32: 923 if (arg_is_const(op->args[2])) { 924 tmp = arg_info(op->args[2])->val & 31; 925 mask = (uint32_t)arg_info(op->args[1])->mask >> tmp; 926 } 927 break; 928 case INDEX_op_shr_i64: 929 if (arg_is_const(op->args[2])) { 930 tmp = arg_info(op->args[2])->val & 63; 931 mask = (uint64_t)arg_info(op->args[1])->mask >> tmp; 932 } 933 break; 934 935 case INDEX_op_extrl_i64_i32: 936 mask = (uint32_t)arg_info(op->args[1])->mask; 937 break; 938 case INDEX_op_extrh_i64_i32: 939 mask = (uint64_t)arg_info(op->args[1])->mask >> 32; 940 break; 941 942 CASE_OP_32_64(shl): 943 if (arg_is_const(op->args[2])) { 944 tmp = arg_info(op->args[2])->val & (TCG_TARGET_REG_BITS - 1); 945 mask = arg_info(op->args[1])->mask << tmp; 946 } 947 break; 948 949 CASE_OP_32_64(neg): 950 /* Set to 1 all bits to the left of the rightmost. */ 951 mask = -(arg_info(op->args[1])->mask 952 & -arg_info(op->args[1])->mask); 953 break; 954 955 CASE_OP_32_64(deposit): 956 mask = deposit64(arg_info(op->args[1])->mask, 957 op->args[3], op->args[4], 958 arg_info(op->args[2])->mask); 959 break; 960 961 CASE_OP_32_64(extract): 962 mask = extract64(arg_info(op->args[1])->mask, 963 op->args[2], op->args[3]); 964 if (op->args[2] == 0) { 965 affected = arg_info(op->args[1])->mask & ~mask; 966 } 967 break; 968 CASE_OP_32_64(sextract): 969 mask = sextract64(arg_info(op->args[1])->mask, 970 op->args[2], op->args[3]); 971 if (op->args[2] == 0 && (tcg_target_long)mask >= 0) { 972 affected = arg_info(op->args[1])->mask & ~mask; 973 } 974 break; 975 976 CASE_OP_32_64(or): 977 CASE_OP_32_64(xor): 978 mask = arg_info(op->args[1])->mask | arg_info(op->args[2])->mask; 979 break; 980 981 case INDEX_op_clz_i32: 982 case INDEX_op_ctz_i32: 983 mask = arg_info(op->args[2])->mask | 31; 984 break; 985 986 case INDEX_op_clz_i64: 987 case INDEX_op_ctz_i64: 988 mask = arg_info(op->args[2])->mask | 63; 989 break; 990 991 case INDEX_op_ctpop_i32: 992 mask = 32 | 31; 993 break; 994 case INDEX_op_ctpop_i64: 995 mask = 64 | 63; 996 break; 997 998 CASE_OP_32_64(setcond): 999 case INDEX_op_setcond2_i32: 1000 mask = 1; 1001 break; 1002 1003 CASE_OP_32_64(movcond): 1004 mask = arg_info(op->args[3])->mask | arg_info(op->args[4])->mask; 1005 break; 1006 1007 CASE_OP_32_64(ld8u): 1008 mask = 0xff; 1009 break; 1010 CASE_OP_32_64(ld16u): 1011 mask = 0xffff; 1012 break; 1013 case INDEX_op_ld32u_i64: 1014 mask = 0xffffffffu; 1015 break; 1016 1017 CASE_OP_32_64(qemu_ld): 1018 { 1019 TCGMemOpIdx oi = op->args[nb_oargs + nb_iargs]; 1020 MemOp mop = get_memop(oi); 1021 if (!(mop & MO_SIGN)) { 1022 mask = (2ULL << ((8 << (mop & MO_SIZE)) - 1)) - 1; 1023 } 1024 } 1025 break; 1026 1027 default: 1028 break; 1029 } 1030 1031 /* 32-bit ops generate 32-bit results. For the result is zero test 1032 below, we can ignore high bits, but for further optimizations we 1033 need to record that the high bits contain garbage. */ 1034 partmask = mask; 1035 if (!(def->flags & TCG_OPF_64BIT)) { 1036 mask |= ~(tcg_target_ulong)0xffffffffu; 1037 partmask &= 0xffffffffu; 1038 affected &= 0xffffffffu; 1039 } 1040 1041 if (partmask == 0) { 1042 tcg_debug_assert(nb_oargs == 1); 1043 tcg_opt_gen_movi(s, op, op->args[0], 0); 1044 continue; 1045 } 1046 if (affected == 0) { 1047 tcg_debug_assert(nb_oargs == 1); 1048 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]); 1049 continue; 1050 } 1051 1052 /* Simplify expression for "op r, a, 0 => movi r, 0" cases */ 1053 switch (opc) { 1054 CASE_OP_32_64_VEC(and): 1055 CASE_OP_32_64_VEC(mul): 1056 CASE_OP_32_64(muluh): 1057 CASE_OP_32_64(mulsh): 1058 if (arg_is_const(op->args[2]) 1059 && arg_info(op->args[2])->val == 0) { 1060 tcg_opt_gen_movi(s, op, op->args[0], 0); 1061 continue; 1062 } 1063 break; 1064 default: 1065 break; 1066 } 1067 1068 /* Simplify expression for "op r, a, a => mov r, a" cases */ 1069 switch (opc) { 1070 CASE_OP_32_64_VEC(or): 1071 CASE_OP_32_64_VEC(and): 1072 if (args_are_copies(op->args[1], op->args[2])) { 1073 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]); 1074 continue; 1075 } 1076 break; 1077 default: 1078 break; 1079 } 1080 1081 /* Simplify expression for "op r, a, a => movi r, 0" cases */ 1082 switch (opc) { 1083 CASE_OP_32_64_VEC(andc): 1084 CASE_OP_32_64_VEC(sub): 1085 CASE_OP_32_64_VEC(xor): 1086 if (args_are_copies(op->args[1], op->args[2])) { 1087 tcg_opt_gen_movi(s, op, op->args[0], 0); 1088 continue; 1089 } 1090 break; 1091 default: 1092 break; 1093 } 1094 1095 /* Propagate constants through copy operations and do constant 1096 folding. Constants will be substituted to arguments by register 1097 allocator where needed and possible. Also detect copies. */ 1098 switch (opc) { 1099 CASE_OP_32_64_VEC(mov): 1100 tcg_opt_gen_mov(s, op, op->args[0], op->args[1]); 1101 break; 1102 CASE_OP_32_64(movi): 1103 case INDEX_op_dupi_vec: 1104 tcg_opt_gen_movi(s, op, op->args[0], op->args[1]); 1105 break; 1106 1107 case INDEX_op_dup_vec: 1108 if (arg_is_const(op->args[1])) { 1109 tmp = arg_info(op->args[1])->val; 1110 tmp = dup_const(TCGOP_VECE(op), tmp); 1111 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1112 break; 1113 } 1114 goto do_default; 1115 1116 case INDEX_op_dup2_vec: 1117 assert(TCG_TARGET_REG_BITS == 32); 1118 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) { 1119 tmp = arg_info(op->args[1])->val; 1120 if (tmp == arg_info(op->args[2])->val) { 1121 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1122 break; 1123 } 1124 } else if (args_are_copies(op->args[1], op->args[2])) { 1125 op->opc = INDEX_op_dup_vec; 1126 TCGOP_VECE(op) = MO_32; 1127 nb_iargs = 1; 1128 } 1129 goto do_default; 1130 1131 CASE_OP_32_64(not): 1132 CASE_OP_32_64(neg): 1133 CASE_OP_32_64(ext8s): 1134 CASE_OP_32_64(ext8u): 1135 CASE_OP_32_64(ext16s): 1136 CASE_OP_32_64(ext16u): 1137 CASE_OP_32_64(ctpop): 1138 CASE_OP_32_64(bswap16): 1139 CASE_OP_32_64(bswap32): 1140 case INDEX_op_bswap64_i64: 1141 case INDEX_op_ext32s_i64: 1142 case INDEX_op_ext32u_i64: 1143 case INDEX_op_ext_i32_i64: 1144 case INDEX_op_extu_i32_i64: 1145 case INDEX_op_extrl_i64_i32: 1146 case INDEX_op_extrh_i64_i32: 1147 if (arg_is_const(op->args[1])) { 1148 tmp = do_constant_folding(opc, arg_info(op->args[1])->val, 0); 1149 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1150 break; 1151 } 1152 goto do_default; 1153 1154 CASE_OP_32_64(add): 1155 CASE_OP_32_64(sub): 1156 CASE_OP_32_64(mul): 1157 CASE_OP_32_64(or): 1158 CASE_OP_32_64(and): 1159 CASE_OP_32_64(xor): 1160 CASE_OP_32_64(shl): 1161 CASE_OP_32_64(shr): 1162 CASE_OP_32_64(sar): 1163 CASE_OP_32_64(rotl): 1164 CASE_OP_32_64(rotr): 1165 CASE_OP_32_64(andc): 1166 CASE_OP_32_64(orc): 1167 CASE_OP_32_64(eqv): 1168 CASE_OP_32_64(nand): 1169 CASE_OP_32_64(nor): 1170 CASE_OP_32_64(muluh): 1171 CASE_OP_32_64(mulsh): 1172 CASE_OP_32_64(div): 1173 CASE_OP_32_64(divu): 1174 CASE_OP_32_64(rem): 1175 CASE_OP_32_64(remu): 1176 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) { 1177 tmp = do_constant_folding(opc, arg_info(op->args[1])->val, 1178 arg_info(op->args[2])->val); 1179 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1180 break; 1181 } 1182 goto do_default; 1183 1184 CASE_OP_32_64(clz): 1185 CASE_OP_32_64(ctz): 1186 if (arg_is_const(op->args[1])) { 1187 TCGArg v = arg_info(op->args[1])->val; 1188 if (v != 0) { 1189 tmp = do_constant_folding(opc, v, 0); 1190 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1191 } else { 1192 tcg_opt_gen_mov(s, op, op->args[0], op->args[2]); 1193 } 1194 break; 1195 } 1196 goto do_default; 1197 1198 CASE_OP_32_64(deposit): 1199 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) { 1200 tmp = deposit64(arg_info(op->args[1])->val, 1201 op->args[3], op->args[4], 1202 arg_info(op->args[2])->val); 1203 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1204 break; 1205 } 1206 goto do_default; 1207 1208 CASE_OP_32_64(extract): 1209 if (arg_is_const(op->args[1])) { 1210 tmp = extract64(arg_info(op->args[1])->val, 1211 op->args[2], op->args[3]); 1212 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1213 break; 1214 } 1215 goto do_default; 1216 1217 CASE_OP_32_64(sextract): 1218 if (arg_is_const(op->args[1])) { 1219 tmp = sextract64(arg_info(op->args[1])->val, 1220 op->args[2], op->args[3]); 1221 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1222 break; 1223 } 1224 goto do_default; 1225 1226 CASE_OP_32_64(extract2): 1227 if (arg_is_const(op->args[1]) && arg_is_const(op->args[2])) { 1228 TCGArg v1 = arg_info(op->args[1])->val; 1229 TCGArg v2 = arg_info(op->args[2])->val; 1230 1231 if (opc == INDEX_op_extract2_i64) { 1232 tmp = (v1 >> op->args[3]) | (v2 << (64 - op->args[3])); 1233 } else { 1234 tmp = (int32_t)(((uint32_t)v1 >> op->args[3]) | 1235 ((uint32_t)v2 << (32 - op->args[3]))); 1236 } 1237 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1238 break; 1239 } 1240 goto do_default; 1241 1242 CASE_OP_32_64(setcond): 1243 tmp = do_constant_folding_cond(opc, op->args[1], 1244 op->args[2], op->args[3]); 1245 if (tmp != 2) { 1246 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1247 break; 1248 } 1249 goto do_default; 1250 1251 CASE_OP_32_64(brcond): 1252 tmp = do_constant_folding_cond(opc, op->args[0], 1253 op->args[1], op->args[2]); 1254 if (tmp != 2) { 1255 if (tmp) { 1256 bitmap_zero(temps_used.l, nb_temps); 1257 op->opc = INDEX_op_br; 1258 op->args[0] = op->args[3]; 1259 } else { 1260 tcg_op_remove(s, op); 1261 } 1262 break; 1263 } 1264 goto do_default; 1265 1266 CASE_OP_32_64(movcond): 1267 tmp = do_constant_folding_cond(opc, op->args[1], 1268 op->args[2], op->args[5]); 1269 if (tmp != 2) { 1270 tcg_opt_gen_mov(s, op, op->args[0], op->args[4-tmp]); 1271 break; 1272 } 1273 if (arg_is_const(op->args[3]) && arg_is_const(op->args[4])) { 1274 tcg_target_ulong tv = arg_info(op->args[3])->val; 1275 tcg_target_ulong fv = arg_info(op->args[4])->val; 1276 TCGCond cond = op->args[5]; 1277 if (fv == 1 && tv == 0) { 1278 cond = tcg_invert_cond(cond); 1279 } else if (!(tv == 1 && fv == 0)) { 1280 goto do_default; 1281 } 1282 op->args[3] = cond; 1283 op->opc = opc = (opc == INDEX_op_movcond_i32 1284 ? INDEX_op_setcond_i32 1285 : INDEX_op_setcond_i64); 1286 nb_iargs = 2; 1287 } 1288 goto do_default; 1289 1290 case INDEX_op_add2_i32: 1291 case INDEX_op_sub2_i32: 1292 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3]) 1293 && arg_is_const(op->args[4]) && arg_is_const(op->args[5])) { 1294 uint32_t al = arg_info(op->args[2])->val; 1295 uint32_t ah = arg_info(op->args[3])->val; 1296 uint32_t bl = arg_info(op->args[4])->val; 1297 uint32_t bh = arg_info(op->args[5])->val; 1298 uint64_t a = ((uint64_t)ah << 32) | al; 1299 uint64_t b = ((uint64_t)bh << 32) | bl; 1300 TCGArg rl, rh; 1301 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32); 1302 1303 if (opc == INDEX_op_add2_i32) { 1304 a += b; 1305 } else { 1306 a -= b; 1307 } 1308 1309 rl = op->args[0]; 1310 rh = op->args[1]; 1311 tcg_opt_gen_movi(s, op, rl, (int32_t)a); 1312 tcg_opt_gen_movi(s, op2, rh, (int32_t)(a >> 32)); 1313 break; 1314 } 1315 goto do_default; 1316 1317 case INDEX_op_mulu2_i32: 1318 if (arg_is_const(op->args[2]) && arg_is_const(op->args[3])) { 1319 uint32_t a = arg_info(op->args[2])->val; 1320 uint32_t b = arg_info(op->args[3])->val; 1321 uint64_t r = (uint64_t)a * b; 1322 TCGArg rl, rh; 1323 TCGOp *op2 = tcg_op_insert_before(s, op, INDEX_op_movi_i32); 1324 1325 rl = op->args[0]; 1326 rh = op->args[1]; 1327 tcg_opt_gen_movi(s, op, rl, (int32_t)r); 1328 tcg_opt_gen_movi(s, op2, rh, (int32_t)(r >> 32)); 1329 break; 1330 } 1331 goto do_default; 1332 1333 case INDEX_op_brcond2_i32: 1334 tmp = do_constant_folding_cond2(&op->args[0], &op->args[2], 1335 op->args[4]); 1336 if (tmp != 2) { 1337 if (tmp) { 1338 do_brcond_true: 1339 bitmap_zero(temps_used.l, nb_temps); 1340 op->opc = INDEX_op_br; 1341 op->args[0] = op->args[5]; 1342 } else { 1343 do_brcond_false: 1344 tcg_op_remove(s, op); 1345 } 1346 } else if ((op->args[4] == TCG_COND_LT 1347 || op->args[4] == TCG_COND_GE) 1348 && arg_is_const(op->args[2]) 1349 && arg_info(op->args[2])->val == 0 1350 && arg_is_const(op->args[3]) 1351 && arg_info(op->args[3])->val == 0) { 1352 /* Simplify LT/GE comparisons vs zero to a single compare 1353 vs the high word of the input. */ 1354 do_brcond_high: 1355 bitmap_zero(temps_used.l, nb_temps); 1356 op->opc = INDEX_op_brcond_i32; 1357 op->args[0] = op->args[1]; 1358 op->args[1] = op->args[3]; 1359 op->args[2] = op->args[4]; 1360 op->args[3] = op->args[5]; 1361 } else if (op->args[4] == TCG_COND_EQ) { 1362 /* Simplify EQ comparisons where one of the pairs 1363 can be simplified. */ 1364 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1365 op->args[0], op->args[2], 1366 TCG_COND_EQ); 1367 if (tmp == 0) { 1368 goto do_brcond_false; 1369 } else if (tmp == 1) { 1370 goto do_brcond_high; 1371 } 1372 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1373 op->args[1], op->args[3], 1374 TCG_COND_EQ); 1375 if (tmp == 0) { 1376 goto do_brcond_false; 1377 } else if (tmp != 1) { 1378 goto do_default; 1379 } 1380 do_brcond_low: 1381 bitmap_zero(temps_used.l, nb_temps); 1382 op->opc = INDEX_op_brcond_i32; 1383 op->args[1] = op->args[2]; 1384 op->args[2] = op->args[4]; 1385 op->args[3] = op->args[5]; 1386 } else if (op->args[4] == TCG_COND_NE) { 1387 /* Simplify NE comparisons where one of the pairs 1388 can be simplified. */ 1389 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1390 op->args[0], op->args[2], 1391 TCG_COND_NE); 1392 if (tmp == 0) { 1393 goto do_brcond_high; 1394 } else if (tmp == 1) { 1395 goto do_brcond_true; 1396 } 1397 tmp = do_constant_folding_cond(INDEX_op_brcond_i32, 1398 op->args[1], op->args[3], 1399 TCG_COND_NE); 1400 if (tmp == 0) { 1401 goto do_brcond_low; 1402 } else if (tmp == 1) { 1403 goto do_brcond_true; 1404 } 1405 goto do_default; 1406 } else { 1407 goto do_default; 1408 } 1409 break; 1410 1411 case INDEX_op_setcond2_i32: 1412 tmp = do_constant_folding_cond2(&op->args[1], &op->args[3], 1413 op->args[5]); 1414 if (tmp != 2) { 1415 do_setcond_const: 1416 tcg_opt_gen_movi(s, op, op->args[0], tmp); 1417 } else if ((op->args[5] == TCG_COND_LT 1418 || op->args[5] == TCG_COND_GE) 1419 && arg_is_const(op->args[3]) 1420 && arg_info(op->args[3])->val == 0 1421 && arg_is_const(op->args[4]) 1422 && arg_info(op->args[4])->val == 0) { 1423 /* Simplify LT/GE comparisons vs zero to a single compare 1424 vs the high word of the input. */ 1425 do_setcond_high: 1426 reset_temp(op->args[0]); 1427 arg_info(op->args[0])->mask = 1; 1428 op->opc = INDEX_op_setcond_i32; 1429 op->args[1] = op->args[2]; 1430 op->args[2] = op->args[4]; 1431 op->args[3] = op->args[5]; 1432 } else if (op->args[5] == TCG_COND_EQ) { 1433 /* Simplify EQ comparisons where one of the pairs 1434 can be simplified. */ 1435 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1436 op->args[1], op->args[3], 1437 TCG_COND_EQ); 1438 if (tmp == 0) { 1439 goto do_setcond_const; 1440 } else if (tmp == 1) { 1441 goto do_setcond_high; 1442 } 1443 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1444 op->args[2], op->args[4], 1445 TCG_COND_EQ); 1446 if (tmp == 0) { 1447 goto do_setcond_high; 1448 } else if (tmp != 1) { 1449 goto do_default; 1450 } 1451 do_setcond_low: 1452 reset_temp(op->args[0]); 1453 arg_info(op->args[0])->mask = 1; 1454 op->opc = INDEX_op_setcond_i32; 1455 op->args[2] = op->args[3]; 1456 op->args[3] = op->args[5]; 1457 } else if (op->args[5] == TCG_COND_NE) { 1458 /* Simplify NE comparisons where one of the pairs 1459 can be simplified. */ 1460 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1461 op->args[1], op->args[3], 1462 TCG_COND_NE); 1463 if (tmp == 0) { 1464 goto do_setcond_high; 1465 } else if (tmp == 1) { 1466 goto do_setcond_const; 1467 } 1468 tmp = do_constant_folding_cond(INDEX_op_setcond_i32, 1469 op->args[2], op->args[4], 1470 TCG_COND_NE); 1471 if (tmp == 0) { 1472 goto do_setcond_low; 1473 } else if (tmp == 1) { 1474 goto do_setcond_const; 1475 } 1476 goto do_default; 1477 } else { 1478 goto do_default; 1479 } 1480 break; 1481 1482 case INDEX_op_call: 1483 if (!(op->args[nb_oargs + nb_iargs + 1] 1484 & (TCG_CALL_NO_READ_GLOBALS | TCG_CALL_NO_WRITE_GLOBALS))) { 1485 for (i = 0; i < nb_globals; i++) { 1486 if (test_bit(i, temps_used.l)) { 1487 reset_ts(&s->temps[i]); 1488 } 1489 } 1490 } 1491 goto do_reset_output; 1492 1493 default: 1494 do_default: 1495 /* Default case: we know nothing about operation (or were unable 1496 to compute the operation result) so no propagation is done. 1497 We trash everything if the operation is the end of a basic 1498 block, otherwise we only trash the output args. "mask" is 1499 the non-zero bits mask for the first output arg. */ 1500 if (def->flags & TCG_OPF_BB_END) { 1501 bitmap_zero(temps_used.l, nb_temps); 1502 } else { 1503 do_reset_output: 1504 for (i = 0; i < nb_oargs; i++) { 1505 reset_temp(op->args[i]); 1506 /* Save the corresponding known-zero bits mask for the 1507 first output argument (only one supported so far). */ 1508 if (i == 0) { 1509 arg_info(op->args[i])->mask = mask; 1510 } 1511 } 1512 } 1513 break; 1514 } 1515 1516 /* Eliminate duplicate and redundant fence instructions. */ 1517 if (prev_mb) { 1518 switch (opc) { 1519 case INDEX_op_mb: 1520 /* Merge two barriers of the same type into one, 1521 * or a weaker barrier into a stronger one, 1522 * or two weaker barriers into a stronger one. 1523 * mb X; mb Y => mb X|Y 1524 * mb; strl => mb; st 1525 * ldaq; mb => ld; mb 1526 * ldaq; strl => ld; mb; st 1527 * Other combinations are also merged into a strong 1528 * barrier. This is stricter than specified but for 1529 * the purposes of TCG is better than not optimizing. 1530 */ 1531 prev_mb->args[0] |= op->args[0]; 1532 tcg_op_remove(s, op); 1533 break; 1534 1535 default: 1536 /* Opcodes that end the block stop the optimization. */ 1537 if ((def->flags & TCG_OPF_BB_END) == 0) { 1538 break; 1539 } 1540 /* fallthru */ 1541 case INDEX_op_qemu_ld_i32: 1542 case INDEX_op_qemu_ld_i64: 1543 case INDEX_op_qemu_st_i32: 1544 case INDEX_op_qemu_st_i64: 1545 case INDEX_op_call: 1546 /* Opcodes that touch guest memory stop the optimization. */ 1547 prev_mb = NULL; 1548 break; 1549 } 1550 } else if (opc == INDEX_op_mb) { 1551 prev_mb = op; 1552 } 1553 } 1554 } 1555