1 /* IR-agnostic target query functions relating to optabs 2 Copyright (C) 1987-2018 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 #include "vec-perm-indices.h" 32 33 struct target_optabs default_target_optabs; 34 struct target_optabs *this_fn_optabs = &default_target_optabs; 35 #if SWITCHABLE_TARGET 36 struct target_optabs *this_target_optabs = &default_target_optabs; 37 #endif 38 39 /* Return the insn used to perform conversion OP from mode FROM_MODE 40 to mode TO_MODE; return CODE_FOR_nothing if the target does not have 41 such an insn, or if it is unsuitable for optimization type OPT_TYPE. */ 42 43 insn_code 44 convert_optab_handler (convert_optab optab, machine_mode to_mode, 45 machine_mode from_mode, optimization_type opt_type) 46 { 47 insn_code icode = convert_optab_handler (optab, to_mode, from_mode); 48 if (icode == CODE_FOR_nothing 49 || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type)) 50 return CODE_FOR_nothing; 51 return icode; 52 } 53 54 /* Return the insn used to implement mode MODE of OP; return 55 CODE_FOR_nothing if the target does not have such an insn, 56 or if it is unsuitable for optimization type OPT_TYPE. */ 57 58 insn_code 59 direct_optab_handler (convert_optab optab, machine_mode mode, 60 optimization_type opt_type) 61 { 62 insn_code icode = direct_optab_handler (optab, mode); 63 if (icode == CODE_FOR_nothing 64 || !targetm.optab_supported_p (optab, mode, mode, opt_type)) 65 return CODE_FOR_nothing; 66 return icode; 67 } 68 69 /* Enumerates the possible types of structure operand to an 70 extraction_insn. */ 71 enum extraction_type { ET_unaligned_mem, ET_reg }; 72 73 /* Check whether insv, extv or extzv pattern ICODE can be used for an 74 insertion or extraction of type TYPE on a structure of mode MODE. 75 Return true if so and fill in *INSN accordingly. STRUCT_OP is the 76 operand number of the structure (the first sign_extract or zero_extract 77 operand) and FIELD_OP is the operand number of the field (the other 78 side of the set from the sign_extract or zero_extract). */ 79 80 static bool 81 get_traditional_extraction_insn (extraction_insn *insn, 82 enum extraction_type type, 83 machine_mode mode, 84 enum insn_code icode, 85 int struct_op, int field_op) 86 { 87 const struct insn_data_d *data = &insn_data[icode]; 88 89 machine_mode struct_mode = data->operand[struct_op].mode; 90 if (struct_mode == VOIDmode) 91 struct_mode = word_mode; 92 if (mode != struct_mode) 93 return false; 94 95 machine_mode field_mode = data->operand[field_op].mode; 96 if (field_mode == VOIDmode) 97 field_mode = word_mode; 98 99 machine_mode pos_mode = data->operand[struct_op + 2].mode; 100 if (pos_mode == VOIDmode) 101 pos_mode = word_mode; 102 103 insn->icode = icode; 104 insn->field_mode = as_a <scalar_int_mode> (field_mode); 105 if (type == ET_unaligned_mem) 106 insn->struct_mode = byte_mode; 107 else if (struct_mode == BLKmode) 108 insn->struct_mode = opt_scalar_int_mode (); 109 else 110 insn->struct_mode = as_a <scalar_int_mode> (struct_mode); 111 insn->pos_mode = as_a <scalar_int_mode> (pos_mode); 112 return true; 113 } 114 115 /* Return true if an optab exists to perform an insertion or extraction 116 of type TYPE in mode MODE. Describe the instruction in *INSN if so. 117 118 REG_OPTAB is the optab to use for register structures and 119 MISALIGN_OPTAB is the optab to use for misaligned memory structures. 120 POS_OP is the operand number of the bit position. */ 121 122 static bool 123 get_optab_extraction_insn (struct extraction_insn *insn, 124 enum extraction_type type, 125 machine_mode mode, direct_optab reg_optab, 126 direct_optab misalign_optab, int pos_op) 127 { 128 direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab); 129 enum insn_code icode = direct_optab_handler (optab, mode); 130 if (icode == CODE_FOR_nothing) 131 return false; 132 133 const struct insn_data_d *data = &insn_data[icode]; 134 135 machine_mode pos_mode = data->operand[pos_op].mode; 136 if (pos_mode == VOIDmode) 137 pos_mode = word_mode; 138 139 insn->icode = icode; 140 insn->field_mode = as_a <scalar_int_mode> (mode); 141 if (type == ET_unaligned_mem) 142 insn->struct_mode = opt_scalar_int_mode (); 143 else 144 insn->struct_mode = insn->field_mode; 145 insn->pos_mode = as_a <scalar_int_mode> (pos_mode); 146 return true; 147 } 148 149 /* Return true if an instruction exists to perform an insertion or 150 extraction (PATTERN says which) of type TYPE in mode MODE. 151 Describe the instruction in *INSN if so. */ 152 153 static bool 154 get_extraction_insn (extraction_insn *insn, 155 enum extraction_pattern pattern, 156 enum extraction_type type, 157 machine_mode mode) 158 { 159 switch (pattern) 160 { 161 case EP_insv: 162 if (targetm.have_insv () 163 && get_traditional_extraction_insn (insn, type, mode, 164 targetm.code_for_insv, 0, 3)) 165 return true; 166 return get_optab_extraction_insn (insn, type, mode, insv_optab, 167 insvmisalign_optab, 2); 168 169 case EP_extv: 170 if (targetm.have_extv () 171 && get_traditional_extraction_insn (insn, type, mode, 172 targetm.code_for_extv, 1, 0)) 173 return true; 174 return get_optab_extraction_insn (insn, type, mode, extv_optab, 175 extvmisalign_optab, 3); 176 177 case EP_extzv: 178 if (targetm.have_extzv () 179 && get_traditional_extraction_insn (insn, type, mode, 180 targetm.code_for_extzv, 1, 0)) 181 return true; 182 return get_optab_extraction_insn (insn, type, mode, extzv_optab, 183 extzvmisalign_optab, 3); 184 185 default: 186 gcc_unreachable (); 187 } 188 } 189 190 /* Return true if an instruction exists to access a field of mode 191 FIELDMODE in a structure that has STRUCT_BITS significant bits. 192 Describe the "best" such instruction in *INSN if so. PATTERN and 193 TYPE describe the type of insertion or extraction we want to perform. 194 195 For an insertion, the number of significant structure bits includes 196 all bits of the target. For an extraction, it need only include the 197 most significant bit of the field. Larger widths are acceptable 198 in both cases. */ 199 200 static bool 201 get_best_extraction_insn (extraction_insn *insn, 202 enum extraction_pattern pattern, 203 enum extraction_type type, 204 unsigned HOST_WIDE_INT struct_bits, 205 machine_mode field_mode) 206 { 207 opt_scalar_int_mode mode_iter; 208 FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits)) 209 { 210 scalar_int_mode mode = mode_iter.require (); 211 if (get_extraction_insn (insn, pattern, type, mode)) 212 { 213 FOR_EACH_MODE_FROM (mode_iter, mode) 214 { 215 mode = mode_iter.require (); 216 if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode)) 217 || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode, 218 field_mode)) 219 break; 220 get_extraction_insn (insn, pattern, type, mode); 221 } 222 return true; 223 } 224 } 225 return false; 226 } 227 228 /* Return true if an instruction exists to access a field of mode 229 FIELDMODE in a register structure that has STRUCT_BITS significant bits. 230 Describe the "best" such instruction in *INSN if so. PATTERN describes 231 the type of insertion or extraction we want to perform. 232 233 For an insertion, the number of significant structure bits includes 234 all bits of the target. For an extraction, it need only include the 235 most significant bit of the field. Larger widths are acceptable 236 in both cases. */ 237 238 bool 239 get_best_reg_extraction_insn (extraction_insn *insn, 240 enum extraction_pattern pattern, 241 unsigned HOST_WIDE_INT struct_bits, 242 machine_mode field_mode) 243 { 244 return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits, 245 field_mode); 246 } 247 248 /* Return true if an instruction exists to access a field of BITSIZE 249 bits starting BITNUM bits into a memory structure. Describe the 250 "best" such instruction in *INSN if so. PATTERN describes the type 251 of insertion or extraction we want to perform and FIELDMODE is the 252 natural mode of the extracted field. 253 254 The instructions considered here only access bytes that overlap 255 the bitfield; they do not touch any surrounding bytes. */ 256 257 bool 258 get_best_mem_extraction_insn (extraction_insn *insn, 259 enum extraction_pattern pattern, 260 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum, 261 machine_mode field_mode) 262 { 263 unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT 264 + bitsize 265 + BITS_PER_UNIT - 1); 266 struct_bits -= struct_bits % BITS_PER_UNIT; 267 return get_best_extraction_insn (insn, pattern, ET_unaligned_mem, 268 struct_bits, field_mode); 269 } 270 271 /* Return the insn code used to extend FROM_MODE to TO_MODE. 272 UNSIGNEDP specifies zero-extension instead of sign-extension. If 273 no such operation exists, CODE_FOR_nothing will be returned. */ 274 275 enum insn_code 276 can_extend_p (machine_mode to_mode, machine_mode from_mode, 277 int unsignedp) 278 { 279 if (unsignedp < 0 && targetm.have_ptr_extend ()) 280 return targetm.code_for_ptr_extend; 281 282 convert_optab tab = unsignedp ? zext_optab : sext_optab; 283 return convert_optab_handler (tab, to_mode, from_mode); 284 } 285 286 /* Return the insn code to convert fixed-point mode FIXMODE to floating-point 287 mode FLTMODE, or CODE_FOR_nothing if no such instruction exists. 288 UNSIGNEDP specifies whether FIXMODE is unsigned. */ 289 290 enum insn_code 291 can_float_p (machine_mode fltmode, machine_mode fixmode, 292 int unsignedp) 293 { 294 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab; 295 return convert_optab_handler (tab, fltmode, fixmode); 296 } 297 298 /* Return the insn code to convert floating-point mode FLTMODE to fixed-point 299 mode FIXMODE, or CODE_FOR_nothing if no such instruction exists. 300 UNSIGNEDP specifies whether FIXMODE is unsigned. 301 302 On a successful return, set *TRUNCP_PTR to true if it is necessary to 303 output an explicit FTRUNC before the instruction. */ 304 305 enum insn_code 306 can_fix_p (machine_mode fixmode, machine_mode fltmode, 307 int unsignedp, bool *truncp_ptr) 308 { 309 convert_optab tab; 310 enum insn_code icode; 311 312 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab; 313 icode = convert_optab_handler (tab, fixmode, fltmode); 314 if (icode != CODE_FOR_nothing) 315 { 316 *truncp_ptr = false; 317 return icode; 318 } 319 320 /* FIXME: This requires a port to define both FIX and FTRUNC pattern 321 for this to work. We need to rework the fix* and ftrunc* patterns 322 and documentation. */ 323 tab = unsignedp ? ufix_optab : sfix_optab; 324 icode = convert_optab_handler (tab, fixmode, fltmode); 325 if (icode != CODE_FOR_nothing 326 && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing) 327 { 328 *truncp_ptr = true; 329 return icode; 330 } 331 332 return CODE_FOR_nothing; 333 } 334 335 /* Return nonzero if a conditional move of mode MODE is supported. 336 337 This function is for combine so it can tell whether an insn that looks 338 like a conditional move is actually supported by the hardware. If we 339 guess wrong we lose a bit on optimization, but that's it. */ 340 /* ??? sparc64 supports conditionally moving integers values based on fp 341 comparisons, and vice versa. How do we handle them? */ 342 343 bool 344 can_conditionally_move_p (machine_mode mode) 345 { 346 return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing; 347 } 348 349 /* If a target doesn't implement a permute on a vector with multibyte 350 elements, we can try to do the same permute on byte elements. 351 If this makes sense for vector mode MODE then return the appropriate 352 byte vector mode. */ 353 354 opt_machine_mode 355 qimode_for_vec_perm (machine_mode mode) 356 { 357 machine_mode qimode; 358 if (GET_MODE_INNER (mode) != QImode 359 && mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode) 360 && VECTOR_MODE_P (qimode)) 361 return qimode; 362 return opt_machine_mode (); 363 } 364 365 /* Return true if selector SEL can be represented in the integer 366 equivalent of vector mode MODE. */ 367 368 bool 369 selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel) 370 { 371 unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode)); 372 return (mask == HOST_WIDE_INT_M1U 373 || sel.all_in_range_p (0, mask + 1)); 374 } 375 376 /* Return true if VEC_PERM_EXPRs with variable selector operands can be 377 expanded using SIMD extensions of the CPU. MODE is the mode of the 378 vectors being permuted. */ 379 380 bool 381 can_vec_perm_var_p (machine_mode mode) 382 { 383 /* If the target doesn't implement a vector mode for the vector type, 384 then no operations are supported. */ 385 if (!VECTOR_MODE_P (mode)) 386 return false; 387 388 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) 389 return true; 390 391 /* We allow fallback to a QI vector mode, and adjust the mask. */ 392 machine_mode qimode; 393 if (!qimode_for_vec_perm (mode).exists (&qimode) 394 || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1)) 395 return false; 396 397 if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing) 398 return false; 399 400 /* In order to support the lowering of variable permutations, 401 we need to support shifts and adds. */ 402 if (GET_MODE_UNIT_SIZE (mode) > 2 403 && optab_handler (ashl_optab, mode) == CODE_FOR_nothing 404 && optab_handler (vashl_optab, mode) == CODE_FOR_nothing) 405 return false; 406 if (optab_handler (add_optab, qimode) == CODE_FOR_nothing) 407 return false; 408 409 return true; 410 } 411 412 /* Return true if the target directly supports VEC_PERM_EXPRs on vectors 413 of mode MODE using the selector SEL. ALLOW_VARIABLE_P is true if it 414 is acceptable to force the selector into a register and use a variable 415 permute (if the target supports that). 416 417 Note that additional permutations representing whole-vector shifts may 418 also be handled via the vec_shr optab, but only where the second input 419 vector is entirely constant zeroes; this case is not dealt with here. */ 420 421 bool 422 can_vec_perm_const_p (machine_mode mode, const vec_perm_indices &sel, 423 bool allow_variable_p) 424 { 425 /* If the target doesn't implement a vector mode for the vector type, 426 then no operations are supported. */ 427 if (!VECTOR_MODE_P (mode)) 428 return false; 429 430 /* It's probably cheaper to test for the variable case first. */ 431 if (allow_variable_p && selector_fits_mode_p (mode, sel)) 432 { 433 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) 434 return true; 435 436 /* Unlike can_vec_perm_var_p, we don't need to test for optabs 437 related computing the QImode selector, since that happens at 438 compile time. */ 439 machine_mode qimode; 440 if (qimode_for_vec_perm (mode).exists (&qimode)) 441 { 442 vec_perm_indices qimode_indices; 443 qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode)); 444 if (selector_fits_mode_p (qimode, qimode_indices) 445 && (direct_optab_handler (vec_perm_optab, qimode) 446 != CODE_FOR_nothing)) 447 return true; 448 } 449 } 450 451 if (targetm.vectorize.vec_perm_const != NULL) 452 { 453 if (targetm.vectorize.vec_perm_const (mode, NULL_RTX, NULL_RTX, 454 NULL_RTX, sel)) 455 return true; 456 457 /* ??? For completeness, we ought to check the QImode version of 458 vec_perm_const_optab. But all users of this implicit lowering 459 feature implement the variable vec_perm_optab, and the ia64 460 port specifically doesn't want us to lower V2SF operations 461 into integer operations. */ 462 } 463 464 return false; 465 } 466 467 /* Find a widening optab even if it doesn't widen as much as we want. 468 E.g. if from_mode is HImode, and to_mode is DImode, and there is no 469 direct HI->SI insn, then return SI->DI, if that exists. */ 470 471 enum insn_code 472 find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, 473 machine_mode from_mode, 474 machine_mode *found_mode) 475 { 476 machine_mode limit_mode = to_mode; 477 if (is_a <scalar_int_mode> (from_mode)) 478 { 479 gcc_checking_assert (is_a <scalar_int_mode> (to_mode) 480 && known_lt (GET_MODE_PRECISION (from_mode), 481 GET_MODE_PRECISION (to_mode))); 482 /* The modes after FROM_MODE are all MODE_INT, so the only 483 MODE_PARTIAL_INT mode we consider is FROM_MODE itself. 484 If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing 485 MODE_INT. */ 486 if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT) 487 limit_mode = GET_MODE_WIDER_MODE (limit_mode).require (); 488 } 489 else 490 gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode) 491 && from_mode < to_mode); 492 FOR_EACH_MODE (from_mode, from_mode, limit_mode) 493 { 494 enum insn_code handler = convert_optab_handler (op, to_mode, from_mode); 495 496 if (handler != CODE_FOR_nothing) 497 { 498 if (found_mode) 499 *found_mode = from_mode; 500 return handler; 501 } 502 } 503 504 return CODE_FOR_nothing; 505 } 506 507 /* Return non-zero if a highpart multiply is supported of can be synthisized. 508 For the benefit of expand_mult_highpart, the return value is 1 for direct, 509 2 for even/odd widening, and 3 for hi/lo widening. */ 510 511 int 512 can_mult_highpart_p (machine_mode mode, bool uns_p) 513 { 514 optab op; 515 516 op = uns_p ? umul_highpart_optab : smul_highpart_optab; 517 if (optab_handler (op, mode) != CODE_FOR_nothing) 518 return 1; 519 520 /* If the mode is an integral vector, synth from widening operations. */ 521 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) 522 return 0; 523 524 poly_int64 nunits = GET_MODE_NUNITS (mode); 525 526 op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab; 527 if (optab_handler (op, mode) != CODE_FOR_nothing) 528 { 529 op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab; 530 if (optab_handler (op, mode) != CODE_FOR_nothing) 531 { 532 /* The encoding has 2 interleaved stepped patterns. */ 533 vec_perm_builder sel (nunits, 2, 3); 534 for (unsigned int i = 0; i < 6; ++i) 535 sel.quick_push (!BYTES_BIG_ENDIAN 536 + (i & ~1) 537 + ((i & 1) ? nunits : 0)); 538 vec_perm_indices indices (sel, 2, nunits); 539 if (can_vec_perm_const_p (mode, indices)) 540 return 2; 541 } 542 } 543 544 op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab; 545 if (optab_handler (op, mode) != CODE_FOR_nothing) 546 { 547 op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab; 548 if (optab_handler (op, mode) != CODE_FOR_nothing) 549 { 550 /* The encoding has a single stepped pattern. */ 551 vec_perm_builder sel (nunits, 1, 3); 552 for (unsigned int i = 0; i < 3; ++i) 553 sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1)); 554 vec_perm_indices indices (sel, 2, nunits); 555 if (can_vec_perm_const_p (mode, indices)) 556 return 3; 557 } 558 } 559 560 return 0; 561 } 562 563 /* Return true if target supports vector masked load/store for mode. */ 564 565 bool 566 can_vec_mask_load_store_p (machine_mode mode, 567 machine_mode mask_mode, 568 bool is_load) 569 { 570 optab op = is_load ? maskload_optab : maskstore_optab; 571 machine_mode vmode; 572 573 /* If mode is vector mode, check it directly. */ 574 if (VECTOR_MODE_P (mode)) 575 return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; 576 577 /* Otherwise, return true if there is some vector mode with 578 the mask load/store supported. */ 579 580 /* See if there is any chance the mask load or store might be 581 vectorized. If not, punt. */ 582 scalar_mode smode; 583 if (!is_a <scalar_mode> (mode, &smode)) 584 return false; 585 586 vmode = targetm.vectorize.preferred_simd_mode (smode); 587 if (!VECTOR_MODE_P (vmode)) 588 return false; 589 590 if ((targetm.vectorize.get_mask_mode 591 (GET_MODE_NUNITS (vmode), GET_MODE_SIZE (vmode)).exists (&mask_mode)) 592 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) 593 return true; 594 595 auto_vector_sizes vector_sizes; 596 targetm.vectorize.autovectorize_vector_sizes (&vector_sizes); 597 for (unsigned int i = 0; i < vector_sizes.length (); ++i) 598 { 599 poly_uint64 cur = vector_sizes[i]; 600 poly_uint64 nunits; 601 if (!multiple_p (cur, GET_MODE_SIZE (smode), &nunits)) 602 continue; 603 if (mode_for_vector (smode, nunits).exists (&vmode) 604 && VECTOR_MODE_P (vmode) 605 && targetm.vectorize.get_mask_mode (nunits, cur).exists (&mask_mode) 606 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) 607 return true; 608 } 609 return false; 610 } 611 612 /* Return true if there is a compare_and_swap pattern. */ 613 614 bool 615 can_compare_and_swap_p (machine_mode mode, bool allow_libcall) 616 { 617 enum insn_code icode; 618 619 /* Check for __atomic_compare_and_swap. */ 620 icode = direct_optab_handler (atomic_compare_and_swap_optab, mode); 621 if (icode != CODE_FOR_nothing) 622 return true; 623 624 /* Check for __sync_compare_and_swap. */ 625 icode = optab_handler (sync_compare_and_swap_optab, mode); 626 if (icode != CODE_FOR_nothing) 627 return true; 628 if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode)) 629 return true; 630 631 /* No inline compare and swap. */ 632 return false; 633 } 634 635 /* Return true if an atomic exchange can be performed. */ 636 637 bool 638 can_atomic_exchange_p (machine_mode mode, bool allow_libcall) 639 { 640 enum insn_code icode; 641 642 /* Check for __atomic_exchange. */ 643 icode = direct_optab_handler (atomic_exchange_optab, mode); 644 if (icode != CODE_FOR_nothing) 645 return true; 646 647 /* Don't check __sync_test_and_set, as on some platforms that 648 has reduced functionality. Targets that really do support 649 a proper exchange should simply be updated to the __atomics. */ 650 651 return can_compare_and_swap_p (mode, allow_libcall); 652 } 653 654 /* Return true if an atomic load can be performed without falling back to 655 a compare-and-swap. */ 656 657 bool 658 can_atomic_load_p (machine_mode mode) 659 { 660 enum insn_code icode; 661 662 /* Does the target supports the load directly? */ 663 icode = direct_optab_handler (atomic_load_optab, mode); 664 if (icode != CODE_FOR_nothing) 665 return true; 666 667 /* If the size of the object is greater than word size on this target, 668 then we assume that a load will not be atomic. Also see 669 expand_atomic_load. */ 670 return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD); 671 } 672 673 /* Determine whether "1 << x" is relatively cheap in word_mode. */ 674 675 bool 676 lshift_cheap_p (bool speed_p) 677 { 678 /* FIXME: This should be made target dependent via this "this_target" 679 mechanism, similar to e.g. can_copy_init_p in gcse.c. */ 680 static bool init[2] = { false, false }; 681 static bool cheap[2] = { true, true }; 682 683 /* If the targer has no lshift in word_mode, the operation will most 684 probably not be cheap. ??? Does GCC even work for such targets? */ 685 if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing) 686 return false; 687 688 if (!init[speed_p]) 689 { 690 rtx reg = gen_raw_REG (word_mode, 10000); 691 int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg), 692 word_mode, speed_p); 693 cheap[speed_p] = cost < COSTS_N_INSNS (3); 694 init[speed_p] = true; 695 } 696 697 return cheap[speed_p]; 698 } 699 700 /* Return true if optab OP supports at least one mode. */ 701 702 static bool 703 supports_at_least_one_mode_p (optab op) 704 { 705 for (int i = 0; i < NUM_MACHINE_MODES; ++i) 706 if (direct_optab_handler (op, (machine_mode) i) != CODE_FOR_nothing) 707 return true; 708 709 return false; 710 } 711 712 /* Return true if vec_gather_load is available for at least one vector 713 mode. */ 714 715 bool 716 supports_vec_gather_load_p () 717 { 718 if (this_fn_optabs->supports_vec_gather_load_cached) 719 return this_fn_optabs->supports_vec_gather_load; 720 721 this_fn_optabs->supports_vec_gather_load_cached = true; 722 723 this_fn_optabs->supports_vec_gather_load 724 = supports_at_least_one_mode_p (gather_load_optab); 725 726 return this_fn_optabs->supports_vec_gather_load; 727 } 728 729 /* Return true if vec_scatter_store is available for at least one vector 730 mode. */ 731 732 bool 733 supports_vec_scatter_store_p () 734 { 735 if (this_fn_optabs->supports_vec_scatter_store_cached) 736 return this_fn_optabs->supports_vec_scatter_store; 737 738 this_fn_optabs->supports_vec_scatter_store_cached = true; 739 740 this_fn_optabs->supports_vec_scatter_store 741 = supports_at_least_one_mode_p (scatter_store_optab); 742 743 return this_fn_optabs->supports_vec_scatter_store; 744 } 745 746