Mercurial > hg > CbC > CbC_gcc
comparison gcc/optabs-query.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
comparison
equal
deleted
inserted
replaced
111:04ced10e8804 | 131:84e7813d76e9 |
---|---|
1 /* IR-agnostic target query functions relating to optabs | 1 /* IR-agnostic target query functions relating to optabs |
2 Copyright (C) 1987-2017 Free Software Foundation, Inc. | 2 Copyright (C) 1987-2018 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify it under | 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 | 7 the terms of the GNU General Public License as published by the Free |
26 #include "optabs-query.h" | 26 #include "optabs-query.h" |
27 #include "optabs-libfuncs.h" | 27 #include "optabs-libfuncs.h" |
28 #include "insn-config.h" | 28 #include "insn-config.h" |
29 #include "rtl.h" | 29 #include "rtl.h" |
30 #include "recog.h" | 30 #include "recog.h" |
31 #include "vec-perm-indices.h" | |
31 | 32 |
32 struct target_optabs default_target_optabs; | 33 struct target_optabs default_target_optabs; |
33 struct target_optabs *this_fn_optabs = &default_target_optabs; | 34 struct target_optabs *this_fn_optabs = &default_target_optabs; |
34 #if SWITCHABLE_TARGET | 35 #if SWITCHABLE_TARGET |
35 struct target_optabs *this_target_optabs = &default_target_optabs; | 36 struct target_optabs *this_target_optabs = &default_target_optabs; |
210 if (get_extraction_insn (insn, pattern, type, mode)) | 211 if (get_extraction_insn (insn, pattern, type, mode)) |
211 { | 212 { |
212 FOR_EACH_MODE_FROM (mode_iter, mode) | 213 FOR_EACH_MODE_FROM (mode_iter, mode) |
213 { | 214 { |
214 mode = mode_iter.require (); | 215 mode = mode_iter.require (); |
215 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (field_mode) | 216 if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode)) |
216 || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode, | 217 || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode, |
217 field_mode)) | 218 field_mode)) |
218 break; | 219 break; |
219 get_extraction_insn (insn, pattern, type, mode); | 220 get_extraction_insn (insn, pattern, type, mode); |
220 } | 221 } |
343 can_conditionally_move_p (machine_mode mode) | 344 can_conditionally_move_p (machine_mode mode) |
344 { | 345 { |
345 return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing; | 346 return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing; |
346 } | 347 } |
347 | 348 |
348 /* Return true if VEC_PERM_EXPR of arbitrary input vectors can be | 349 /* If a target doesn't implement a permute on a vector with multibyte |
349 expanded using SIMD extensions of the CPU. SEL may be NULL, which | 350 elements, we can try to do the same permute on byte elements. |
350 stands for an unknown constant. Note that additional permutations | 351 If this makes sense for vector mode MODE then return the appropriate |
351 representing whole-vector shifts may also be handled via the vec_shr | 352 byte vector mode. */ |
352 optab, but only where the second input vector is entirely constant | 353 |
353 zeroes; this case is not dealt with here. */ | 354 opt_machine_mode |
354 | 355 qimode_for_vec_perm (machine_mode mode) |
355 bool | |
356 can_vec_perm_p (machine_mode mode, bool variable, vec_perm_indices *sel) | |
357 { | 356 { |
358 machine_mode qimode; | 357 machine_mode qimode; |
359 | 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 { | |
360 /* If the target doesn't implement a vector mode for the vector type, | 383 /* If the target doesn't implement a vector mode for the vector type, |
361 then no operations are supported. */ | 384 then no operations are supported. */ |
362 if (!VECTOR_MODE_P (mode)) | 385 if (!VECTOR_MODE_P (mode)) |
363 return false; | 386 return false; |
364 | 387 |
365 if (!variable) | |
366 { | |
367 if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing | |
368 && (sel == NULL | |
369 || targetm.vectorize.vec_perm_const_ok == NULL | |
370 || targetm.vectorize.vec_perm_const_ok (mode, *sel))) | |
371 return true; | |
372 } | |
373 | |
374 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) | 388 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing) |
375 return true; | 389 return true; |
376 | 390 |
377 /* We allow fallback to a QI vector mode, and adjust the mask. */ | 391 /* We allow fallback to a QI vector mode, and adjust the mask. */ |
378 if (GET_MODE_INNER (mode) == QImode | 392 machine_mode qimode; |
379 || !mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode) | 393 if (!qimode_for_vec_perm (mode).exists (&qimode) |
380 || !VECTOR_MODE_P (qimode)) | 394 || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1)) |
381 return false; | 395 return false; |
382 | 396 |
383 /* ??? For completeness, we ought to check the QImode version of | |
384 vec_perm_const_optab. But all users of this implicit lowering | |
385 feature implement the variable vec_perm_optab. */ | |
386 if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing) | 397 if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing) |
387 return false; | 398 return false; |
388 | 399 |
389 /* In order to support the lowering of variable permutations, | 400 /* In order to support the lowering of variable permutations, |
390 we need to support shifts and adds. */ | 401 we need to support shifts and adds. */ |
391 if (variable) | 402 if (GET_MODE_UNIT_SIZE (mode) > 2 |
392 { | 403 && optab_handler (ashl_optab, mode) == CODE_FOR_nothing |
393 if (GET_MODE_UNIT_SIZE (mode) > 2 | 404 && optab_handler (vashl_optab, mode) == CODE_FOR_nothing) |
394 && optab_handler (ashl_optab, mode) == CODE_FOR_nothing | 405 return false; |
395 && optab_handler (vashl_optab, mode) == CODE_FOR_nothing) | 406 if (optab_handler (add_optab, qimode) == CODE_FOR_nothing) |
396 return false; | 407 return false; |
397 if (optab_handler (add_optab, qimode) == CODE_FOR_nothing) | |
398 return false; | |
399 } | |
400 | 408 |
401 return true; | 409 return true; |
402 } | 410 } |
403 | 411 |
404 /* Like optab_handler, but for widening_operations that have a | 412 /* Return true if the target directly supports VEC_PERM_EXPRs on vectors |
405 TO_MODE and a FROM_MODE. */ | 413 of mode MODE using the selector SEL. ALLOW_VARIABLE_P is true if it |
406 | 414 is acceptable to force the selector into a register and use a variable |
407 enum insn_code | 415 permute (if the target supports that). |
408 widening_optab_handler (optab op, machine_mode to_mode, | 416 |
409 machine_mode from_mode) | 417 Note that additional permutations representing whole-vector shifts may |
410 { | 418 also be handled via the vec_shr optab, but only where the second input |
411 unsigned scode = (op << 16) | to_mode; | 419 vector is entirely constant zeroes; this case is not dealt with here. */ |
412 if (to_mode != from_mode && from_mode != VOIDmode) | 420 |
413 { | 421 bool |
414 /* ??? Why does find_widening_optab_handler_and_mode attempt to | 422 can_vec_perm_const_p (machine_mode mode, const vec_perm_indices &sel, |
415 widen things that can't be widened? E.g. add_optab... */ | 423 bool allow_variable_p) |
416 if (op > LAST_CONV_OPTAB) | 424 { |
417 return CODE_FOR_nothing; | 425 /* If the target doesn't implement a vector mode for the vector type, |
418 scode |= from_mode << 8; | 426 then no operations are supported. */ |
419 } | 427 if (!VECTOR_MODE_P (mode)) |
420 return raw_optab_handler (scode); | 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; | |
421 } | 465 } |
422 | 466 |
423 /* Find a widening optab even if it doesn't widen as much as we want. | 467 /* Find a widening optab even if it doesn't widen as much as we want. |
424 E.g. if from_mode is HImode, and to_mode is DImode, and there is no | 468 E.g. if from_mode is HImode, and to_mode is DImode, and there is no |
425 direct HI->SI insn, then return SI->DI, if that exists. | 469 direct HI->SI insn, then return SI->DI, if that exists. */ |
426 If PERMIT_NON_WIDENING is non-zero then this can be used with | |
427 non-widening optabs also. */ | |
428 | 470 |
429 enum insn_code | 471 enum insn_code |
430 find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, | 472 find_widening_optab_handler_and_mode (optab op, machine_mode to_mode, |
431 machine_mode from_mode, | 473 machine_mode from_mode, |
432 int permit_non_widening, | |
433 machine_mode *found_mode) | 474 machine_mode *found_mode) |
434 { | 475 { |
435 for (; (permit_non_widening || from_mode != to_mode) | 476 machine_mode limit_mode = to_mode; |
436 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode) | 477 if (is_a <scalar_int_mode> (from_mode)) |
437 && from_mode != VOIDmode; | 478 { |
438 from_mode = GET_MODE_WIDER_MODE (from_mode).else_void ()) | 479 gcc_checking_assert (is_a <scalar_int_mode> (to_mode) |
439 { | 480 && known_lt (GET_MODE_PRECISION (from_mode), |
440 enum insn_code handler = widening_optab_handler (op, to_mode, | 481 GET_MODE_PRECISION (to_mode))); |
441 from_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); | |
442 | 495 |
443 if (handler != CODE_FOR_nothing) | 496 if (handler != CODE_FOR_nothing) |
444 { | 497 { |
445 if (found_mode) | 498 if (found_mode) |
446 *found_mode = from_mode; | 499 *found_mode = from_mode; |
457 | 510 |
458 int | 511 int |
459 can_mult_highpart_p (machine_mode mode, bool uns_p) | 512 can_mult_highpart_p (machine_mode mode, bool uns_p) |
460 { | 513 { |
461 optab op; | 514 optab op; |
462 unsigned i, nunits; | |
463 | 515 |
464 op = uns_p ? umul_highpart_optab : smul_highpart_optab; | 516 op = uns_p ? umul_highpart_optab : smul_highpart_optab; |
465 if (optab_handler (op, mode) != CODE_FOR_nothing) | 517 if (optab_handler (op, mode) != CODE_FOR_nothing) |
466 return 1; | 518 return 1; |
467 | 519 |
468 /* If the mode is an integral vector, synth from widening operations. */ | 520 /* If the mode is an integral vector, synth from widening operations. */ |
469 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) | 521 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT) |
470 return 0; | 522 return 0; |
471 | 523 |
472 nunits = GET_MODE_NUNITS (mode); | 524 poly_int64 nunits = GET_MODE_NUNITS (mode); |
473 | 525 |
474 op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab; | 526 op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab; |
475 if (optab_handler (op, mode) != CODE_FOR_nothing) | 527 if (optab_handler (op, mode) != CODE_FOR_nothing) |
476 { | 528 { |
477 op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab; | 529 op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab; |
478 if (optab_handler (op, mode) != CODE_FOR_nothing) | 530 if (optab_handler (op, mode) != CODE_FOR_nothing) |
479 { | 531 { |
480 auto_vec_perm_indices sel (nunits); | 532 /* The encoding has 2 interleaved stepped patterns. */ |
481 for (i = 0; i < nunits; ++i) | 533 vec_perm_builder sel (nunits, 2, 3); |
534 for (unsigned int i = 0; i < 6; ++i) | |
482 sel.quick_push (!BYTES_BIG_ENDIAN | 535 sel.quick_push (!BYTES_BIG_ENDIAN |
483 + (i & ~1) | 536 + (i & ~1) |
484 + ((i & 1) ? nunits : 0)); | 537 + ((i & 1) ? nunits : 0)); |
485 if (can_vec_perm_p (mode, false, &sel)) | 538 vec_perm_indices indices (sel, 2, nunits); |
539 if (can_vec_perm_const_p (mode, indices)) | |
486 return 2; | 540 return 2; |
487 } | 541 } |
488 } | 542 } |
489 | 543 |
490 op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab; | 544 op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab; |
491 if (optab_handler (op, mode) != CODE_FOR_nothing) | 545 if (optab_handler (op, mode) != CODE_FOR_nothing) |
492 { | 546 { |
493 op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab; | 547 op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab; |
494 if (optab_handler (op, mode) != CODE_FOR_nothing) | 548 if (optab_handler (op, mode) != CODE_FOR_nothing) |
495 { | 549 { |
496 auto_vec_perm_indices sel (nunits); | 550 /* The encoding has a single stepped pattern. */ |
497 for (i = 0; i < nunits; ++i) | 551 vec_perm_builder sel (nunits, 1, 3); |
552 for (unsigned int i = 0; i < 3; ++i) | |
498 sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1)); | 553 sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1)); |
499 if (can_vec_perm_p (mode, false, &sel)) | 554 vec_perm_indices indices (sel, 2, nunits); |
555 if (can_vec_perm_const_p (mode, indices)) | |
500 return 3; | 556 return 3; |
501 } | 557 } |
502 } | 558 } |
503 | 559 |
504 return 0; | 560 return 0; |
511 machine_mode mask_mode, | 567 machine_mode mask_mode, |
512 bool is_load) | 568 bool is_load) |
513 { | 569 { |
514 optab op = is_load ? maskload_optab : maskstore_optab; | 570 optab op = is_load ? maskload_optab : maskstore_optab; |
515 machine_mode vmode; | 571 machine_mode vmode; |
516 unsigned int vector_sizes; | |
517 | 572 |
518 /* If mode is vector mode, check it directly. */ | 573 /* If mode is vector mode, check it directly. */ |
519 if (VECTOR_MODE_P (mode)) | 574 if (VECTOR_MODE_P (mode)) |
520 return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; | 575 return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing; |
521 | 576 |
535 if ((targetm.vectorize.get_mask_mode | 590 if ((targetm.vectorize.get_mask_mode |
536 (GET_MODE_NUNITS (vmode), GET_MODE_SIZE (vmode)).exists (&mask_mode)) | 591 (GET_MODE_NUNITS (vmode), GET_MODE_SIZE (vmode)).exists (&mask_mode)) |
537 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) | 592 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) |
538 return true; | 593 return true; |
539 | 594 |
540 vector_sizes = targetm.vectorize.autovectorize_vector_sizes (); | 595 auto_vector_sizes vector_sizes; |
541 while (vector_sizes != 0) | 596 targetm.vectorize.autovectorize_vector_sizes (&vector_sizes); |
542 { | 597 for (unsigned int i = 0; i < vector_sizes.length (); ++i) |
543 unsigned int cur = 1 << floor_log2 (vector_sizes); | 598 { |
544 vector_sizes &= ~cur; | 599 poly_uint64 cur = vector_sizes[i]; |
545 if (cur <= GET_MODE_SIZE (smode)) | 600 poly_uint64 nunits; |
601 if (!multiple_p (cur, GET_MODE_SIZE (smode), &nunits)) | |
546 continue; | 602 continue; |
547 unsigned int nunits = cur / GET_MODE_SIZE (smode); | |
548 if (mode_for_vector (smode, nunits).exists (&vmode) | 603 if (mode_for_vector (smode, nunits).exists (&vmode) |
549 && VECTOR_MODE_P (vmode) | 604 && VECTOR_MODE_P (vmode) |
550 && targetm.vectorize.get_mask_mode (nunits, cur).exists (&mask_mode) | 605 && targetm.vectorize.get_mask_mode (nunits, cur).exists (&mask_mode) |
551 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) | 606 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing) |
552 return true; | 607 return true; |
610 return true; | 665 return true; |
611 | 666 |
612 /* If the size of the object is greater than word size on this target, | 667 /* If the size of the object is greater than word size on this target, |
613 then we assume that a load will not be atomic. Also see | 668 then we assume that a load will not be atomic. Also see |
614 expand_atomic_load. */ | 669 expand_atomic_load. */ |
615 return GET_MODE_PRECISION (mode) <= BITS_PER_WORD; | 670 return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD); |
616 } | 671 } |
617 | 672 |
618 /* Determine whether "1 << x" is relatively cheap in word_mode. */ | 673 /* Determine whether "1 << x" is relatively cheap in word_mode. */ |
619 | 674 |
620 bool | 675 bool |
639 init[speed_p] = true; | 694 init[speed_p] = true; |
640 } | 695 } |
641 | 696 |
642 return cheap[speed_p]; | 697 return cheap[speed_p]; |
643 } | 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 |