1 /* IR-agnostic target query functions relating to optabs 2 Copyright (C) 1987-2017 Free Software Foundation, Inc. 3 4 This file is part of GCC. 5 6 GCC is free software; you can redistribute it and/or modify it under 7 the terms of the GNU General Public License as published by the Free 8 Software Foundation; either version 3, or (at your option) any later 9 version. 10 11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GCC; see the file COPYING3. If not see 18 <http://www.gnu.org/licenses/>. */ 19 20 21 #include "config.h" 22 #include "system.h" 23 #include "coretypes.h" 24 #include "target.h" 25 #include "insn-codes.h" 26 #include "optabs-query.h" 27 #include "optabs-libfuncs.h" 28 #include "insn-config.h" 29 #include "rtl.h" 30 #include "recog.h" 31 32 struct target_optabs default_target_optabs; 33 struct target_optabs *this_fn_optabs = &default_target_optabs; 34 #if SWITCHABLE_TARGET 35 struct target_optabs *this_target_optabs = &default_target_optabs; 36 #endif 37 38 /* Return the insn used to perform conversion OP from mode FROM_MODE 39 to mode TO_MODE; return CODE_FOR_nothing if the target does not have 40 such an insn, or if it is unsuitable for optimization type OPT_TYPE. */ 41 42 insn_code 43 convert_optab_handler (convert_optab optab, machine_mode to_mode, 44 machine_mode from_mode, optimization_type opt_type) 45 { 46 insn_code icode = convert_optab_handler (optab, to_mode, from_mode); 47 if (icode == CODE_FOR_nothing 48 || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type)) 49 return CODE_FOR_nothing; 50 return icode; 51 } 52 53 /* Return the insn used to implement mode MODE of OP; return 54 CODE_FOR_nothing if the target does not have such an insn, 55 or if it is unsuitable for optimization type OPT_TYPE. */ 56 57 insn_code 58 direct_optab_handler (convert_optab optab, machine_mode mode, 59 optimization_type opt_type) 60 { 61 insn_code icode = direct_optab_handler (optab, mode); 62 if (icode == CODE_FOR_nothing 63 || !targetm.optab_supported_p (optab, mode, mode, opt_type)) 64 return CODE_FOR_nothing; 65 return icode; 66 } 67 68 /* Enumerates the possible types of structure operand to an 69 extraction_insn. */ 70 enum extraction_type { ET_unaligned_mem, ET_reg }; 71 72 /* Check whether insv, extv or extzv pattern ICODE can be used for an 73 insertion or extraction of type TYPE on a structure of mode MODE. 74 Return true if so and fill in *INSN accordingly. STRUCT_OP is the 75 operand number of the structure (the first sign_extract or zero_extract 76 operand) and FIELD_OP is the operand number of the field (the other 77 side of the set from the sign_extract or zero_extract). */ 78 79 static bool 80 get_traditional_extraction_insn (extraction_insn *insn, 81 enum extraction_type type, 82 machine_mode mode, 83 enum insn_code icode, 84 int struct_op, int field_op) 85 { 86 const struct insn_data_d *data = &insn_data[icode]; 87 88 machine_mode struct_mode = data->operand[struct_op].mode; 89 if (struct_mode == VOIDmode) 90 struct_mode = word_mode; 91 if (mode != struct_mode) 92 return false; 93 94 machine_mode field_mode = data->operand[field_op].mode; 95 if (field_mode == VOIDmode) 96 field_mode = word_mode; 97 98 machine_mode pos_mode = data->operand[struct_op + 2].mode; 99 if (pos_mode == VOIDmode) 100 pos_mode = word_mode; 101 102 insn->icode = icode; 103 insn->field_mode = field_mode; 104 insn->struct_mode = (type == ET_unaligned_mem ? byte_mode : struct_mode); 105 insn->pos_mode = pos_mode; 106 return true; 107 } 108 109 /* Return true if an optab exists to perform an insertion or extraction 110 of type TYPE in mode MODE. Describe the instruction in *INSN if so. 111 112 REG_OPTAB is the optab to use for register structures and 113 MISALIGN_OPTAB is the optab to use for misaligned memory structures. 114 POS_OP is the operand number of the bit position. */ 115 116 static bool 117 get_optab_extraction_insn (struct extraction_insn *insn, 118 enum extraction_type type, 119 machine_mode mode, direct_optab reg_optab, 120 direct_optab misalign_optab, int pos_op) 121 { 122 direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab); 123 enum insn_code icode = direct_optab_handler (optab, mode); 124 if (icode == CODE_FOR_nothing) 125 return false; 126 127 const struct insn_data_d *data = &insn_data[icode]; 128 129 insn->icode = icode; 130 insn->field_mode = mode; 131 insn->struct_mode = (type == ET_unaligned_mem ? BLKmode : mode); 132 insn->pos_mode = data->operand[pos_op].mode; 133 if (insn->pos_mode == VOIDmode) 134 insn->pos_mode = word_mode; 135 return true; 136 } 137 138 /* Return true if an instruction exists to perform an insertion or 139 extraction (PATTERN says which) of type TYPE in mode MODE. 140 Describe the instruction in *INSN if so. */ 141 142 static bool 143 get_extraction_insn (extraction_insn *insn, 144 enum extraction_pattern pattern, 145 enum extraction_type type, 146 machine_mode mode) 147 { 148 switch (pattern) 149 { 150 case EP_insv: 151 if (targetm.have_insv () 152 && get_traditional_extraction_insn (insn, type, mode, 153 targetm.code_for_insv, 0, 3)) 154 return true; 155 return get_optab_extraction_insn (insn, type, mode, insv_optab, 156 insvmisalign_optab, 2); 157 158 case EP_extv: 159 if (targetm.have_extv () 160 && get_traditional_extraction_insn (insn, type, mode, 161 targetm.code_for_extv, 1, 0)) 162 return true; 163 return get_optab_extraction_insn (insn, type, mode, extv_optab, 164 extvmisalign_optab, 3); 165 166 case EP_extzv: 167 if (targetm.have_extzv () 168 && get_traditional_extraction_insn (insn, type, mode, 169 targetm.code_for_extzv, 1, 0)) 170 return true; 171 return get_optab_extraction_insn (insn, type, mode, extzv_optab, 172 extzvmisalign_optab, 3); 173 174 default: 175 gcc_unreachable (); 176 } 177 } 178 179 /* Return true if an instruction exists to access a field of mode 180 FIELDMODE in a structure that has STRUCT_BITS significant bits. 181 Describe the "best" such instruction in *INSN if so. PATTERN and 182 TYPE describe the type of insertion or extraction we want to perform. 183 184 For an insertion, the number of significant structure bits includes 185 all bits of the target. For an extraction, it need only include the 186 most significant bit of the field. Larger widths are acceptable 187 in both cases. */ 188 189 static bool 190 get_best_extraction_insn (extraction_insn *insn, 191 enum extraction_pattern pattern, 192 enum extraction_type type, 193 unsigned HOST_WIDE_INT struct_bits, 194 machine_mode field_mode) 195 { 196 machine_mode mode = smallest_mode_for_size (struct_bits, MODE_INT); 197 while (mode != VOIDmode) 198 { 199 if (get_extraction_insn (insn, pattern, type, mode)) 200 { 201 while (mode != VOIDmode 202 && GET_MODE_SIZE (mode) <= GET_MODE_SIZE (field_mode) 203 && !TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode, 204 field_mode)) 205 { 206 get_extraction_insn (insn, pattern, type, mode); 207 mode = GET_MODE_WIDER_MODE (mode); 208 } 209 return true; 210 } 211 mode = GET_MODE_WIDER_MODE (mode); 212 } 213 return false; 214 } 215 216 /* Return true if an instruction exists to access a field of mode 217 FIELDMODE in a register structure that has STRUCT_BITS significant bits. 218 Describe the "best" such instruction in *INSN if so. PATTERN describes 219 the type of insertion or extraction we want to perform. 220 221 For an insertion, the number of significant structure bits includes 222 all bits of the target. For an extraction, it need only include the 223 most significant bit of the field. Larger widths are acceptable 224 in both cases. */ 225 226 bool 227 get_best_reg_extraction_insn (extraction_insn *insn, 228 enum extraction_pattern pattern, 229 unsigned HOST_WIDE_INT struct_bits, 230 machine_mode field_mode) 231 { 232 return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits, 233 field_mode); 234 } 235 236 /* Return true if an instruction exists to access a field of BITSIZE 237 bits starting BITNUM bits into a memory structure. Describe the 238 "best" such instruction in *INSN if so. PATTERN describes the type 239 of insertion or extraction we want to perform and FIELDMODE is the 240 natural mode of the extracted field. 241 242 The instructions considered here only access bytes that overlap 243 the bitfield; they do not touch any surrounding bytes. */ 244 245 bool 246 get_best_mem_extraction_insn (extraction_insn *insn, 247 enum extraction_pattern pattern, 248 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum, 249 machine_mode field_mode) 250 { 251 unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT 252 + bitsize 253 + BITS_PER_UNIT - 1); 254 struct_bits -= struct_bits % BITS_PER_UNIT; 255 return get_best_extraction_insn (insn, pattern, ET_unaligned_mem, 256 struct_bits, field_mode); 257 } 258 259 /* Return the insn code used to extend FROM_MODE to TO_MODE. 260 UNSIGNEDP specifies zero-extension instead of sign-extension. If 261 no such operation exists, CODE_FOR_nothing will be returned. */ 262 263 enum insn_code 264 can_extend_p (machine_mode to_mode, machine_mode from_mode, 265 int unsignedp) 266 { 267 if (unsignedp < 0 && targetm.have_ptr_extend ()) 268 return targetm.code_for_ptr_extend; 269 270 convert_optab tab = unsignedp ? zext_optab : sext_optab; 271 return convert_optab_handler (tab, to_mode, from_mode); 272 } 273 274 /* Return the insn code to convert fixed-point mode FIXMODE to floating-point 275 mode FLTMODE, or CODE_FOR_nothing if no such instruction exists. 276 UNSIGNEDP specifies whether FIXMODE is unsigned. */ 277 278 enum insn_code 279 can_float_p (machine_mode fltmode, machine_mode fixmode, 280 int unsignedp) 281 { 282 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab; 283 return convert_optab_handler (tab, fltmode, fixmode); 284 } 285 286 /* Return the insn code to convert floating-point mode FLTMODE to fixed-point 287 mode FIXMODE, or CODE_FOR_nothing if no such instruction exists. 288 UNSIGNEDP specifies whether FIXMODE is unsigned. 289 290 On a successful return, set *TRUNCP_PTR to true if it is necessary to 291 output an explicit FTRUNC before the instruction. */ 292 293 enum insn_code 294 can_fix_p (machine_mode fixmode, machine_mode fltmode, 295 int unsignedp, bool *truncp_ptr) 296 { 297 convert_optab tab; 298 enum insn_code icode; 299 300 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab; 301 icode = convert_optab_handler (tab, fixmode, fltmode); 302 if (icode != CODE_FOR_nothing) 303 { 304 *truncp_ptr = false; 305 return icode; 306 } 307 308 /* FIXME: This requires a port to define both FIX and FTRUNC pattern 309 for this to work. We need to rework the fix* and ftrunc* patterns 310 and documentation. */ 311 tab = unsignedp ? ufix_optab : sfix_optab; 312 icode = convert_optab_handler (tab, fixmode, fltmode); 313 if (icode != CODE_FOR_nothing 314 && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing) 315 { 316 *truncp_ptr = true; 317 return icode; 318 } 319 320 return CODE_FOR_nothing; 321 } 322 323 /* Return nonzero if a conditional move of mode MODE is supported. 324 325 This function is for combine so it can tell whether an insn that looks 326 like a conditional move is actually supported by the hardware. If we 327 guess wrong we lose a bit on optimization, but that's it. */ 328 /* ??? sparc64 supports conditionally moving integers values based on fp 329 comparisons, and vice versa. How do we handle them? */ 330 331 bool 332 can_conditionally_move_p (machine_mode mode) 333 { 334 return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing; 335 } 336 337 /* Return true if VEC_PERM_EXPR of arbitrary input vectors can be 338 expanded using SIMD extensions of the CPU. SEL may be NULL, which 339 stands for an unknown constant. Note that additional permutations 340 representing whole-vector shifts may also be handled via the vec_shr 341 optab, but only where the second input vector is entirely constant 342 zeroes; this case is not dealt with here. */ 343 344 bool 345 can_vec_perm_p (machine_mode mode, bool variable, 346 const unsigned char *sel) 347 { 348 machine_mode qimode; 349 350 /* If the target doesn't implement a vector mode for the vector type, 351 then no operations are supported. */ 352 if (!VECTOR_MODE_P (mode)) 353 return false; 354 355 if (!variable) 356 { 357 if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing 358 && (sel == NULL 359 || targetm.vectorize.vec_perm_const_ok == NULL 360 || targetm.vectorize.vec_perm_const_ok (mode, sel))) 361 return true; 362 } 363 364 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) 365 return true; 366 367 /* We allow fallback to a QI vector mode, and adjust the mask. */ 368 if (GET_MODE_INNER (mode) == QImode) 369 return false; 370 qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode)); 371 if (!VECTOR_MODE_P (qimode)) 372 return false; 373 374 /* ??? For completeness, we ought to check the QImode version of 375 vec_perm_const_optab. But all users of this implicit lowering 376 feature implement the variable vec_perm_optab. */ 377 if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing) 378 return false; 379 380 /* In order to support the lowering of variable permutations, 381 we need to support shifts and adds. */ 382 if (variable) 383 { 384 if (GET_MODE_UNIT_SIZE (mode) > 2 385 && optab_handler (ashl_optab, mode) == CODE_FOR_nothing 386 && optab_handler (vashl_optab, mode) == CODE_FOR_nothing) 387 return false; 388 if (optab_handler (add_optab, qimode) == CODE_FOR_nothing) 389 return false; 390 } 391 392 return true; 393 } 394 395 /* Like optab_handler, but for widening_operations that have a 396 TO_MODE and a FROM_MODE. */ 397 398 enum insn_code 399 widening_optab_handler (optab op, machine_mode to_mode, 400 machine_mode from_mode) 401 { 402 unsigned scode = (op << 16) | to_mode; 403 if (to_mode != from_mode && from_mode != VOIDmode) 404 { 405 /* ??? Why does find_widening_optab_handler_and_mode attempt to 406 widen things that can't be widened? E.g. add_optab... */ 407 if (op > LAST_CONV_OPTAB) 408 return CODE_FOR_nothing; 409 scode |= from_mode << 8; 410 } 411 return raw_optab_handler (scode); 412 } 413 414 /* Find a widening optab even if it doesn't widen as much as we want. 415 E.g. if from_mode is HImode, and to_mode is DImode, and there is no 416 direct HI->SI insn, then return SI->DI, if that exists. 417 If PERMIT_NON_WIDENING is non-zero then this can be used with 418 non-widening optabs also. */ 419 420 enum insn_code 421 find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, 422 machine_mode from_mode, 423 int permit_non_widening, 424 machine_mode *found_mode) 425 { 426 for (; (permit_non_widening || from_mode != to_mode) 427 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode) 428 && from_mode != VOIDmode; 429 from_mode = GET_MODE_WIDER_MODE (from_mode)) 430 { 431 enum insn_code handler = widening_optab_handler (op, to_mode, 432 from_mode); 433 434 if (handler != CODE_FOR_nothing) 435 { 436 if (found_mode) 437 *found_mode = from_mode; 438 return handler; 439 } 440 } 441 442 return CODE_FOR_nothing; 443 } 444 445 /* Return non-zero if a highpart multiply is supported of can be synthisized. 446 For the benefit of expand_mult_highpart, the return value is 1 for direct, 447 2 for even/odd widening, and 3 for hi/lo widening. */ 448 449 int 450 can_mult_highpart_p (machine_mode mode, bool uns_p) 451 { 452 optab op; 453 unsigned char *sel; 454 unsigned i, nunits; 455 456 op = uns_p ? umul_highpart_optab : smul_highpart_optab; 457 if (optab_handler (op, mode) != CODE_FOR_nothing) 458 return 1; 459 460 /* If the mode is an integral vector, synth from widening operations. */ 461 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) 462 return 0; 463 464 nunits = GET_MODE_NUNITS (mode); 465 sel = XALLOCAVEC (unsigned char, nunits); 466 467 op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab; 468 if (optab_handler (op, mode) != CODE_FOR_nothing) 469 { 470 op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab; 471 if (optab_handler (op, mode) != CODE_FOR_nothing) 472 { 473 for (i = 0; i < nunits; ++i) 474 sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0); 475 if (can_vec_perm_p (mode, false, sel)) 476 return 2; 477 } 478 } 479 480 op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab; 481 if (optab_handler (op, mode) != CODE_FOR_nothing) 482 { 483 op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab; 484 if (optab_handler (op, mode) != CODE_FOR_nothing) 485 { 486 for (i = 0; i < nunits; ++i) 487 sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1); 488 if (can_vec_perm_p (mode, false, sel)) 489 return 3; 490 } 491 } 492 493 return 0; 494 } 495 496 /* Return true if target supports vector masked load/store for mode. */ 497 498 bool 499 can_vec_mask_load_store_p (machine_mode mode, 500 machine_mode mask_mode, 501 bool is_load) 502 { 503 optab op = is_load ? maskload_optab : maskstore_optab; 504 machine_mode vmode; 505 unsigned int vector_sizes; 506 507 /* If mode is vector mode, check it directly. */ 508 if (VECTOR_MODE_P (mode)) 509 return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; 510 511 /* Otherwise, return true if there is some vector mode with 512 the mask load/store supported. */ 513 514 /* See if there is any chance the mask load or store might be 515 vectorized. If not, punt. */ 516 vmode = targetm.vectorize.preferred_simd_mode (mode); 517 if (!VECTOR_MODE_P (vmode)) 518 return false; 519 520 mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), 521 GET_MODE_SIZE (vmode)); 522 if (mask_mode == VOIDmode) 523 return false; 524 525 if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) 526 return true; 527 528 vector_sizes = targetm.vectorize.autovectorize_vector_sizes (); 529 while (vector_sizes != 0) 530 { 531 unsigned int cur = 1 << floor_log2 (vector_sizes); 532 vector_sizes &= ~cur; 533 if (cur <= GET_MODE_SIZE (mode)) 534 continue; 535 vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode)); 536 mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode), 537 cur); 538 if (VECTOR_MODE_P (vmode) 539 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) 540 return true; 541 } 542 return false; 543 } 544 545 /* Return true if there is a compare_and_swap pattern. */ 546 547 bool 548 can_compare_and_swap_p (machine_mode mode, bool allow_libcall) 549 { 550 enum insn_code icode; 551 552 /* Check for __atomic_compare_and_swap. */ 553 icode = direct_optab_handler (atomic_compare_and_swap_optab, mode); 554 if (icode != CODE_FOR_nothing) 555 return true; 556 557 /* Check for __sync_compare_and_swap. */ 558 icode = optab_handler (sync_compare_and_swap_optab, mode); 559 if (icode != CODE_FOR_nothing) 560 return true; 561 if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode)) 562 return true; 563 564 /* No inline compare and swap. */ 565 return false; 566 } 567 568 /* Return true if an atomic exchange can be performed. */ 569 570 bool 571 can_atomic_exchange_p (machine_mode mode, bool allow_libcall) 572 { 573 enum insn_code icode; 574 575 /* Check for __atomic_exchange. */ 576 icode = direct_optab_handler (atomic_exchange_optab, mode); 577 if (icode != CODE_FOR_nothing) 578 return true; 579 580 /* Don't check __sync_test_and_set, as on some platforms that 581 has reduced functionality. Targets that really do support 582 a proper exchange should simply be updated to the __atomics. */ 583 584 return can_compare_and_swap_p (mode, allow_libcall); 585 } 586 587 /* Return true if an atomic load can be performed without falling back to 588 a compare-and-swap. */ 589 590 bool 591 can_atomic_load_p (machine_mode mode) 592 { 593 enum insn_code icode; 594 595 /* Does the target supports the load directly? */ 596 icode = direct_optab_handler (atomic_load_optab, mode); 597 if (icode != CODE_FOR_nothing) 598 return true; 599 600 /* If the size of the object is greater than word size on this target, 601 then we assume that a load will not be atomic. Also see 602 expand_atomic_load. */ 603 return GET_MODE_PRECISION (mode) <= BITS_PER_WORD; 604 } 605 606 /* Determine whether "1 << x" is relatively cheap in word_mode. */ 607 608 bool 609 lshift_cheap_p (bool speed_p) 610 { 611 /* FIXME: This should be made target dependent via this "this_target" 612 mechanism, similar to e.g. can_copy_init_p in gcse.c. */ 613 static bool init[2] = { false, false }; 614 static bool cheap[2] = { true, true }; 615 616 /* If the targer has no lshift in word_mode, the operation will most 617 probably not be cheap. ??? Does GCC even work for such targets? */ 618 if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing) 619 return false; 620 621 if (!init[speed_p]) 622 { 623 rtx reg = gen_raw_REG (word_mode, 10000); 624 int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg), 625 word_mode, speed_p); 626 cheap[speed_p] = cost < COSTS_N_INSNS (3); 627 init[speed_p] = true; 628 } 629 630 return cheap[speed_p]; 631 } 632