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