Line data Source code
1 : /* IR-agnostic target query functions relating to optabs
2 : Copyright (C) 1987-2026 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 : #include "internal-fn.h"
33 : #include "memmodel.h"
34 : #include "optabs.h"
35 :
36 : struct target_optabs default_target_optabs;
37 : struct target_optabs *this_fn_optabs = &default_target_optabs;
38 : #if SWITCHABLE_TARGET
39 : struct target_optabs *this_target_optabs = &default_target_optabs;
40 : #endif
41 :
42 : /* Return the insn used to perform conversion OP from mode FROM_MODE
43 : to mode TO_MODE; return CODE_FOR_nothing if the target does not have
44 : such an insn, or if it is unsuitable for optimization type OPT_TYPE. */
45 :
46 : insn_code
47 118837 : convert_optab_handler (convert_optab optab, machine_mode to_mode,
48 : machine_mode from_mode, optimization_type opt_type)
49 : {
50 118837 : insn_code icode = convert_optab_handler (optab, to_mode, from_mode);
51 118837 : if (icode == CODE_FOR_nothing
52 118837 : || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type))
53 118203 : return CODE_FOR_nothing;
54 : return icode;
55 : }
56 :
57 : /* Return the insn used to implement mode MODE of OP; return
58 : CODE_FOR_nothing if the target does not have such an insn,
59 : or if it is unsuitable for optimization type OPT_TYPE. */
60 :
61 : insn_code
62 4183556 : direct_optab_handler (convert_optab optab, machine_mode mode,
63 : optimization_type opt_type)
64 : {
65 4183556 : insn_code icode = direct_optab_handler (optab, mode);
66 4183556 : if (icode == CODE_FOR_nothing
67 4183556 : || !targetm.optab_supported_p (optab, mode, mode, opt_type))
68 3803633 : return CODE_FOR_nothing;
69 : return icode;
70 : }
71 :
72 : /* Enumerates the possible types of structure operand to an
73 : extraction_insn. */
74 : enum extraction_type { ET_unaligned_mem, ET_reg };
75 :
76 : /* Check whether insv, extv or extzv pattern ICODE can be used for an
77 : insertion or extraction of type TYPE on a structure of mode MODE.
78 : Return true if so and fill in *INSN accordingly. STRUCT_OP is the
79 : operand number of the structure (the first sign_extract or zero_extract
80 : operand) and FIELD_OP is the operand number of the field (the other
81 : side of the set from the sign_extract or zero_extract). */
82 :
83 : static bool
84 0 : get_traditional_extraction_insn (extraction_insn *insn,
85 : enum extraction_type type,
86 : machine_mode mode,
87 : enum insn_code icode,
88 : int struct_op, int field_op)
89 : {
90 0 : const struct insn_data_d *data = &insn_data[icode];
91 :
92 0 : machine_mode struct_mode = data->operand[struct_op].mode;
93 0 : if (struct_mode == VOIDmode)
94 0 : struct_mode = word_mode;
95 0 : if (mode != struct_mode)
96 : return false;
97 :
98 0 : machine_mode field_mode = data->operand[field_op].mode;
99 0 : if (field_mode == VOIDmode)
100 0 : field_mode = word_mode;
101 :
102 0 : machine_mode pos_mode = data->operand[struct_op + 2].mode;
103 0 : if (pos_mode == VOIDmode)
104 0 : pos_mode = word_mode;
105 :
106 0 : insn->icode = icode;
107 0 : insn->field_mode = as_a <scalar_int_mode> (field_mode);
108 0 : if (type == ET_unaligned_mem)
109 0 : insn->struct_mode = byte_mode;
110 0 : else if (struct_mode == BLKmode)
111 0 : insn->struct_mode = opt_scalar_int_mode ();
112 : else
113 0 : insn->struct_mode = as_a <scalar_int_mode> (struct_mode);
114 0 : insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
115 0 : return true;
116 : }
117 :
118 : /* Return true if an optab exists to perform an insertion or extraction
119 : of type TYPE in mode MODE. Describe the instruction in *INSN if so.
120 :
121 : REG_OPTAB is the optab to use for register structures and
122 : MISALIGN_OPTAB is the optab to use for misaligned memory structures.
123 : POS_OP is the operand number of the bit position. */
124 :
125 : static bool
126 3534191 : get_optab_extraction_insn (class extraction_insn *insn,
127 : enum extraction_type type,
128 : machine_mode mode, direct_optab reg_optab,
129 : direct_optab misalign_optab, int pos_op)
130 : {
131 3534191 : direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
132 3534191 : enum insn_code icode = direct_optab_handler (optab, mode);
133 3534191 : if (icode == CODE_FOR_nothing)
134 : return false;
135 :
136 1623456 : const struct insn_data_d *data = &insn_data[icode];
137 :
138 1623456 : machine_mode pos_mode = data->operand[pos_op].mode;
139 1623456 : if (pos_mode == VOIDmode)
140 0 : pos_mode = word_mode;
141 :
142 1623456 : insn->icode = icode;
143 1623456 : insn->field_mode = as_a <scalar_int_mode> (mode);
144 1623456 : if (type == ET_unaligned_mem)
145 0 : insn->struct_mode = opt_scalar_int_mode ();
146 : else
147 1623456 : insn->struct_mode = insn->field_mode;
148 1623456 : insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
149 1623456 : return true;
150 : }
151 :
152 : /* Return true if an instruction exists to perform an insertion or
153 : extraction (PATTERN says which) of type TYPE in mode MODE.
154 : Describe the instruction in *INSN if so. */
155 :
156 : static bool
157 3534191 : get_extraction_insn (extraction_insn *insn,
158 : enum extraction_pattern pattern,
159 : enum extraction_type type,
160 : machine_mode mode)
161 : {
162 3534191 : switch (pattern)
163 : {
164 540757 : case EP_insv:
165 540757 : if (targetm.have_insv ()
166 540757 : && get_traditional_extraction_insn (insn, type, mode,
167 : targetm.code_for_insv, 0, 3))
168 : return true;
169 540757 : return get_optab_extraction_insn (insn, type, mode, insv_optab,
170 540757 : insvmisalign_optab, 2);
171 :
172 769004 : case EP_extv:
173 769004 : if (targetm.have_extv ()
174 769004 : && get_traditional_extraction_insn (insn, type, mode,
175 : targetm.code_for_extv, 1, 0))
176 : return true;
177 769004 : return get_optab_extraction_insn (insn, type, mode, extv_optab,
178 769004 : extvmisalign_optab, 3);
179 :
180 2224430 : case EP_extzv:
181 2224430 : if (targetm.have_extzv ()
182 2224430 : && get_traditional_extraction_insn (insn, type, mode,
183 : targetm.code_for_extzv, 1, 0))
184 : return true;
185 2224430 : return get_optab_extraction_insn (insn, type, mode, extzv_optab,
186 2224430 : extzvmisalign_optab, 3);
187 :
188 0 : default:
189 0 : gcc_unreachable ();
190 : }
191 : }
192 :
193 : /* Return true if an instruction exists to access a field of mode
194 : FIELDMODE in a structure that has STRUCT_BITS significant bits.
195 : Describe the "best" such instruction in *INSN if so. PATTERN and
196 : TYPE describe the type of insertion or extraction we want to perform.
197 :
198 : For an insertion, the number of significant structure bits includes
199 : all bits of the target. For an extraction, it need only include the
200 : most significant bit of the field. Larger widths are acceptable
201 : in both cases. */
202 :
203 : static bool
204 1947529 : get_best_extraction_insn (extraction_insn *insn,
205 : enum extraction_pattern pattern,
206 : enum extraction_type type,
207 : unsigned HOST_WIDE_INT struct_bits,
208 : machine_mode field_mode)
209 : {
210 1947529 : opt_scalar_int_mode mode_iter;
211 :
212 3858264 : FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
213 : {
214 3534191 : scalar_int_mode mode = mode_iter.require ();
215 3534191 : if (get_extraction_insn (insn, pattern, type, mode))
216 : {
217 1623456 : FOR_EACH_MODE_FROM (mode_iter, mode)
218 : {
219 1623456 : mode = mode_iter.require ();
220 3246912 : if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
221 1623456 : || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
222 : field_mode))
223 : break;
224 0 : get_extraction_insn (insn, pattern, type, mode);
225 : }
226 1623456 : return true;
227 : }
228 : }
229 : return false;
230 : }
231 :
232 : /* Return true if an instruction exists to access a field of mode
233 : FIELDMODE in a register structure that has STRUCT_BITS significant bits.
234 : Describe the "best" such instruction in *INSN if so. PATTERN describes
235 : the type of insertion or extraction we want to perform.
236 :
237 : For an insertion, the number of significant structure bits includes
238 : all bits of the target. For an extraction, it need only include the
239 : most significant bit of the field. Larger widths are acceptable
240 : in both cases. */
241 :
242 : bool
243 1743221 : get_best_reg_extraction_insn (extraction_insn *insn,
244 : enum extraction_pattern pattern,
245 : unsigned HOST_WIDE_INT struct_bits,
246 : machine_mode field_mode)
247 : {
248 1743221 : return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
249 1743221 : field_mode);
250 : }
251 :
252 : /* Return true if an instruction exists to access a field of BITSIZE
253 : bits starting BITNUM bits into a memory structure. Describe the
254 : "best" such instruction in *INSN if so. PATTERN describes the type
255 : of insertion or extraction we want to perform and FIELDMODE is the
256 : natural mode of the extracted field.
257 :
258 : The instructions considered here only access bytes that overlap
259 : the bitfield; they do not touch any surrounding bytes. */
260 :
261 : bool
262 204308 : get_best_mem_extraction_insn (extraction_insn *insn,
263 : enum extraction_pattern pattern,
264 : HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
265 : machine_mode field_mode)
266 : {
267 204308 : unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
268 204308 : + bitsize
269 204308 : + BITS_PER_UNIT - 1);
270 204308 : struct_bits -= struct_bits % BITS_PER_UNIT;
271 204308 : return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
272 204308 : struct_bits, field_mode);
273 : }
274 :
275 : /* Return the insn code used to extend FROM_MODE to TO_MODE.
276 : UNSIGNEDP specifies zero-extension instead of sign-extension. If
277 : no such operation exists, CODE_FOR_nothing will be returned. */
278 :
279 : enum insn_code
280 5497962 : can_extend_p (machine_mode to_mode, machine_mode from_mode,
281 : int unsignedp)
282 : {
283 5497962 : if (unsignedp < 0 && targetm.have_ptr_extend ())
284 0 : return targetm.code_for_ptr_extend;
285 :
286 5497962 : convert_optab tab = unsignedp ? zext_optab : sext_optab;
287 5497962 : return convert_optab_handler (tab, to_mode, from_mode);
288 : }
289 :
290 : /* Return the insn code to convert fixed-point mode FIXMODE to floating-point
291 : mode FLTMODE, or CODE_FOR_nothing if no such instruction exists.
292 : UNSIGNEDP specifies whether FIXMODE is unsigned. */
293 :
294 : enum insn_code
295 377113 : can_float_p (machine_mode fltmode, machine_mode fixmode,
296 : int unsignedp)
297 : {
298 377113 : convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
299 377113 : return convert_optab_handler (tab, fltmode, fixmode);
300 : }
301 :
302 : /* Return the insn code to convert floating-point mode FLTMODE to fixed-point
303 : mode FIXMODE, or CODE_FOR_nothing if no such instruction exists.
304 : UNSIGNEDP specifies whether FIXMODE is unsigned.
305 :
306 : On a successful return, set *TRUNCP_PTR to true if it is necessary to
307 : output an explicit FTRUNC before the instruction. */
308 :
309 : enum insn_code
310 254238 : can_fix_p (machine_mode fixmode, machine_mode fltmode,
311 : int unsignedp, bool *truncp_ptr)
312 : {
313 254238 : convert_optab tab;
314 254238 : enum insn_code icode;
315 :
316 254238 : tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
317 254238 : icode = convert_optab_handler (tab, fixmode, fltmode);
318 254238 : if (icode != CODE_FOR_nothing)
319 : {
320 51334 : *truncp_ptr = false;
321 51334 : return icode;
322 : }
323 :
324 : /* FIXME: This requires a port to define both FIX and FTRUNC pattern
325 : for this to work. We need to rework the fix* and ftrunc* patterns
326 : and documentation. */
327 202904 : tab = unsignedp ? ufix_optab : sfix_optab;
328 202904 : icode = convert_optab_handler (tab, fixmode, fltmode);
329 202904 : if (icode != CODE_FOR_nothing
330 202904 : && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
331 : {
332 0 : *truncp_ptr = true;
333 0 : return icode;
334 : }
335 :
336 : return CODE_FOR_nothing;
337 : }
338 :
339 : /* Return nonzero if a conditional move of mode MODE is supported.
340 :
341 : This function is for combine so it can tell whether an insn that looks
342 : like a conditional move is actually supported by the hardware. If we
343 : guess wrong we lose a bit on optimization, but that's it. */
344 : /* ??? sparc64 supports conditionally moving integers values based on fp
345 : comparisons, and vice versa. How do we handle them? */
346 :
347 : bool
348 1191043 : can_conditionally_move_p (machine_mode mode)
349 : {
350 1191043 : return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing;
351 : }
352 :
353 : /* If a target doesn't implement a permute on a vector with multibyte
354 : elements, we can try to do the same permute on byte elements.
355 : If this makes sense for vector mode MODE then return the appropriate
356 : byte vector mode. */
357 :
358 : opt_machine_mode
359 780236 : qimode_for_vec_perm (machine_mode mode)
360 : {
361 780236 : if (GET_MODE_INNER (mode) != QImode
362 1512936 : && multiple_p (GET_MODE_PRECISION (GET_MODE_INNER (mode)),
363 732700 : GET_MODE_PRECISION (QImode)))
364 1465400 : return related_vector_mode (mode, QImode, GET_MODE_SIZE (mode));
365 47536 : return opt_machine_mode ();
366 : }
367 :
368 : /* Return true if selector SEL can be represented in the integer
369 : equivalent of vector mode MODE. */
370 :
371 : bool
372 1529618 : selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel)
373 : {
374 1529618 : unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode));
375 1529618 : return (mask == HOST_WIDE_INT_M1U
376 1529618 : || sel.all_in_range_p (0, mask + 1));
377 : }
378 :
379 : /* Return true if VEC_PERM_EXPRs with variable selector operands can be
380 : expanded using SIMD extensions of the CPU. MODE is the mode of the
381 : vectors being permuted. */
382 :
383 : bool
384 880 : can_vec_perm_var_p (machine_mode mode)
385 : {
386 : /* If the target doesn't implement a vector mode for the vector type,
387 : then no operations are supported. */
388 880 : if (!VECTOR_MODE_P (mode))
389 : return false;
390 :
391 629 : if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
392 : return true;
393 :
394 : /* We allow fallback to a QI vector mode, and adjust the mask. */
395 610 : machine_mode qimode;
396 610 : if (!qimode_for_vec_perm (mode).exists (&qimode)
397 988 : || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1))
398 116 : return false;
399 :
400 494 : if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
401 : return false;
402 :
403 : /* In order to support the lowering of variable permutations,
404 : we need to support shifts and adds. */
405 0 : if (GET_MODE_UNIT_SIZE (mode) > 2
406 0 : && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
407 0 : && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
408 : return false;
409 0 : if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
410 : return false;
411 :
412 : return true;
413 : }
414 :
415 : /* Return true if the target directly supports VEC_PERM_EXPRs on vectors
416 : of mode OP_MODE and result vector of mode MODE using the selector SEL.
417 : ALLOW_VARIABLE_P is true if it is acceptable to force the selector into a
418 : register and use a variable permute (if the target supports that). */
419 :
420 : bool
421 909256 : can_vec_perm_const_p (machine_mode mode, machine_mode op_mode,
422 : const vec_perm_indices &sel, bool allow_variable_p)
423 : {
424 : /* If the target doesn't implement a vector mode for the vector type,
425 : then no operations are supported. */
426 909256 : if (!VECTOR_MODE_P (mode))
427 : return false;
428 :
429 : /* It's probably cheaper to test for the variable case first. */
430 907022 : if (op_mode == mode && allow_variable_p && selector_fits_mode_p (mode, sel))
431 : {
432 866217 : if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
433 909256 : return true;
434 :
435 : /* Unlike can_vec_perm_var_p, we don't need to test for optabs
436 : related computing the QImode selector, since that happens at
437 : compile time. */
438 703674 : machine_mode qimode;
439 703674 : if (qimode_for_vec_perm (mode).exists (&qimode))
440 : {
441 663401 : vec_perm_indices qimode_indices;
442 1326802 : qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode));
443 663401 : if (selector_fits_mode_p (qimode, qimode_indices)
444 663401 : && (direct_optab_handler (vec_perm_optab, qimode)
445 : != CODE_FOR_nothing))
446 4 : return true;
447 663401 : }
448 : }
449 :
450 744475 : if (targetm.vectorize.vec_perm_const != NULL)
451 : {
452 744475 : if (targetm.vectorize.vec_perm_const (mode, op_mode, NULL_RTX, NULL_RTX,
453 : NULL_RTX, sel))
454 : return true;
455 :
456 : /* ??? For completeness, we ought to check the QImode version of
457 : vec_perm_const_optab. But all users of this implicit lowering
458 : feature implement the variable vec_perm_optab, and the ia64
459 : port specifically doesn't want us to lower V2SF operations
460 : into integer operations. */
461 : }
462 :
463 24810 : unsigned elements;
464 24810 : if (mode == op_mode
465 47761 : && GET_MODE_NUNITS (mode).is_constant (&elements))
466 : {
467 22951 : if (sel.input_bitwise_zero_p (0)
468 22951 : && can_implement_p (vec_shl_optab, mode))
469 : {
470 : unsigned int first = 0, i;
471 354 : for (i = 0; i < elements; ++i)
472 286 : if (known_eq (poly_uint64 (sel[i]), elements))
473 : {
474 66 : if (i == 0 || first)
475 : break;
476 : first = i;
477 : }
478 440 : else if (first
479 440 : ? maybe_ne (poly_uint64 (sel[i]),
480 75 : elements + i - first)
481 220 : : maybe_ge (poly_uint64 (sel[i]), elements))
482 : break;
483 69 : if (first && i == elements)
484 : return true;
485 : }
486 22885 : if (sel.input_bitwise_zero_p (1)
487 46 : && maybe_ne (sel[0], 0)
488 22885 : && known_lt (sel[0], elements)
489 22921 : && can_implement_p (vec_shr_optab, mode))
490 : {
491 36 : if (sel.series_p (0, 1, sel[0], 1))
492 : return true;
493 : unsigned i;
494 33 : for (i = 1; i < elements; ++i)
495 : {
496 33 : poly_uint64 actual = sel[i];
497 33 : poly_uint64 expected = i + sel[0];
498 : /* Indices into the second vector are all equivalent. */
499 66 : if (maybe_lt (actual, elements)
500 33 : ? maybe_ne (actual, expected)
501 9 : : maybe_lt (expected, elements))
502 : break;
503 : }
504 9 : if (i == elements)
505 : return true;
506 : }
507 : }
508 :
509 : return false;
510 : }
511 :
512 : /* Find a widening optab even if it doesn't widen as much as we want.
513 : E.g. if from_mode is HImode, and to_mode is DImode, and there is no
514 : direct HI->SI insn, then return SI->DI, if that exists. */
515 :
516 : enum insn_code
517 311239 : find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
518 : machine_mode from_mode,
519 : machine_mode *found_mode)
520 : {
521 311239 : machine_mode limit_mode = to_mode;
522 311239 : if (is_a <scalar_int_mode> (from_mode))
523 : {
524 310556 : gcc_checking_assert (is_a <scalar_int_mode> (to_mode)
525 : && known_lt (GET_MODE_PRECISION (from_mode),
526 : GET_MODE_PRECISION (to_mode)));
527 : /* The modes after FROM_MODE are all MODE_INT, so the only
528 : MODE_PARTIAL_INT mode we consider is FROM_MODE itself.
529 : If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing
530 : MODE_INT. */
531 310556 : if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT)
532 0 : limit_mode = GET_MODE_WIDER_MODE (limit_mode).require ();
533 : }
534 683 : else if (is_a <scalar_int_mode> (to_mode))
535 : {
536 0 : gcc_checking_assert (VECTOR_MODE_P (from_mode)
537 : && GET_MODE_INNER (from_mode) < to_mode);
538 0 : limit_mode = GET_MODE_NEXT_MODE (from_mode).require ();
539 : }
540 : else
541 683 : gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
542 : && from_mode < to_mode);
543 584171 : FOR_EACH_MODE (from_mode, from_mode, limit_mode)
544 : {
545 334241 : enum insn_code handler = convert_optab_handler (op, to_mode, from_mode);
546 :
547 334241 : if (handler != CODE_FOR_nothing)
548 : {
549 61309 : if (found_mode)
550 10097 : *found_mode = from_mode;
551 61309 : return handler;
552 : }
553 : }
554 :
555 : return CODE_FOR_nothing;
556 : }
557 :
558 : /* Return non-zero if a highpart multiply is supported or can be synthesized.
559 : For the benefit of expand_mult_highpart, the return value is 1 for direct,
560 : 2 for integral widening, 3 for even/odd widening, 4 for hi/lo widening. */
561 :
562 : int
563 80328 : can_mult_highpart_p (machine_mode mode, bool uns_p)
564 : {
565 80328 : optab op;
566 80328 : scalar_int_mode int_mode, wider_mode;
567 :
568 80328 : op = uns_p ? umul_highpart_optab : smul_highpart_optab;
569 80328 : if (optab_handler (op, mode) != CODE_FOR_nothing)
570 : return 1;
571 :
572 : /* If the mode is integral, synth from widening or larger operations. */
573 76771 : if (is_a <scalar_int_mode> (mode, &int_mode)
574 4783 : && GET_MODE_WIDER_MODE (int_mode).exists (&wider_mode))
575 : {
576 4783 : op = uns_p ? umul_widen_optab : smul_widen_optab;
577 4783 : if (convert_optab_handler (op, wider_mode, mode) != CODE_FOR_nothing)
578 : return 2;
579 :
580 : /* The test on the size comes from expmed_mult_highpart_optab. */
581 4783 : if (optab_handler (smul_optab, wider_mode) != CODE_FOR_nothing
582 4783 : && GET_MODE_BITSIZE (int_mode) - 1 < BITS_PER_WORD)
583 : return 2;
584 : }
585 :
586 : /* If the mode is an integral vector, synth from widening operations. */
587 76771 : if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
588 : return 0;
589 :
590 143976 : poly_int64 nunits = GET_MODE_NUNITS (mode);
591 :
592 71988 : op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
593 71988 : if (optab_handler (op, mode) != CODE_FOR_nothing)
594 : {
595 20830 : op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
596 20830 : if (optab_handler (op, mode) != CODE_FOR_nothing)
597 : {
598 : /* The encoding has 2 interleaved stepped patterns. */
599 20830 : vec_perm_builder sel (nunits, 2, 3);
600 145810 : for (unsigned int i = 0; i < 6; ++i)
601 249960 : sel.quick_push (!BYTES_BIG_ENDIAN
602 124980 : + (i & ~1)
603 187470 : + ((i & 1) ? nunits : 0));
604 20830 : vec_perm_indices indices (sel, 2, nunits);
605 20830 : if (can_vec_perm_const_p (mode, mode, indices))
606 20830 : return 3;
607 20830 : }
608 : }
609 :
610 51158 : op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
611 51158 : if (optab_handler (op, mode) != CODE_FOR_nothing)
612 : {
613 283 : op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
614 283 : if (optab_handler (op, mode) != CODE_FOR_nothing)
615 : {
616 : /* The encoding has a single stepped pattern. */
617 283 : vec_perm_builder sel (nunits, 1, 3);
618 1132 : for (unsigned int i = 0; i < 3; ++i)
619 849 : sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
620 283 : vec_perm_indices indices (sel, 2, nunits);
621 283 : if (can_vec_perm_const_p (mode, mode, indices))
622 283 : return 4;
623 283 : }
624 : }
625 :
626 : return 0;
627 : }
628 :
629 : /* Return true if there is a compare_and_swap pattern. */
630 :
631 : bool
632 164593 : can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
633 : {
634 164593 : enum insn_code icode;
635 :
636 : /* Check for __atomic_compare_and_swap. */
637 164593 : icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
638 164593 : if (icode != CODE_FOR_nothing)
639 : return true;
640 :
641 : /* Check for __sync_compare_and_swap. */
642 137 : icode = optab_handler (sync_compare_and_swap_optab, mode);
643 137 : if (icode != CODE_FOR_nothing)
644 : return true;
645 137 : if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
646 : return true;
647 :
648 : /* No inline compare and swap. */
649 : return false;
650 : }
651 :
652 : /* Return true if an atomic exchange can be performed. */
653 :
654 : bool
655 88 : can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
656 : {
657 88 : enum insn_code icode;
658 :
659 : /* Check for __atomic_exchange. */
660 88 : icode = direct_optab_handler (atomic_exchange_optab, mode);
661 88 : if (icode != CODE_FOR_nothing)
662 : return true;
663 :
664 : /* Don't check __sync_test_and_set, as on some platforms that
665 : has reduced functionality. Targets that really do support
666 : a proper exchange should simply be updated to the __atomics. */
667 :
668 0 : return can_compare_and_swap_p (mode, allow_libcall);
669 : }
670 :
671 : /* Return true if an atomic load can be performed without falling back to
672 : a compare-and-swap. */
673 :
674 : bool
675 219627 : can_atomic_load_p (machine_mode mode)
676 : {
677 219627 : enum insn_code icode;
678 :
679 : /* Does the target supports the load directly? */
680 219627 : icode = direct_optab_handler (atomic_load_optab, mode);
681 219627 : if (icode != CODE_FOR_nothing)
682 : return true;
683 :
684 : /* If the size of the object is greater than word size on this target,
685 : then we assume that a load will not be atomic. Also see
686 : expand_atomic_load. */
687 4046 : return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD);
688 : }
689 :
690 : /* Determine whether "1 << x" is relatively cheap in word_mode. */
691 :
692 : bool
693 1074619 : lshift_cheap_p (bool speed_p)
694 : {
695 : /* FIXME: This should be made target dependent via this "this_target"
696 : mechanism, similar to e.g. can_copy_init_p in gcse.cc. */
697 1074619 : static bool init[2] = { false, false };
698 1074619 : static bool cheap[2] = { true, true };
699 :
700 : /* If the target has no lshift in word_mode, the operation will most
701 : probably not be cheap. ??? Does GCC even work for such targets? */
702 1074619 : if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
703 : return false;
704 :
705 1074619 : if (!init[speed_p])
706 : {
707 41953 : rtx reg = gen_raw_REG (word_mode, 10000);
708 41953 : int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
709 : word_mode, speed_p);
710 41953 : cheap[speed_p] = cost < COSTS_N_INSNS (3);
711 41953 : init[speed_p] = true;
712 : }
713 :
714 1074619 : return cheap[speed_p];
715 : }
716 :
717 : /* If MODE is not VOIDmode, return true if vector conversion optab OP supports
718 : that mode, given that the second mode is always an integer vector.
719 : If MODE is VOIDmode, return true if OP supports any vector mode. */
720 :
721 : static enum insn_code
722 177786 : supported_vec_convert_optab (optab op, machine_mode mode)
723 : {
724 177786 : int start = mode == VOIDmode ? 0 : mode;
725 177786 : int end = mode == VOIDmode ? MAX_MACHINE_MODE - 1 : mode;
726 177786 : enum insn_code icode = CODE_FOR_nothing;
727 355572 : for (int i = start; i <= end; ++i)
728 177786 : if (VECTOR_MODE_P ((machine_mode) i))
729 5511366 : for (int j = MIN_MODE_VECTOR_INT; j < MAX_MODE_VECTOR_INT; ++j)
730 : {
731 10667160 : if ((icode
732 5333580 : = convert_optab_handler (op, (machine_mode) i,
733 : (machine_mode) j)) != CODE_FOR_nothing)
734 : return icode;
735 : }
736 :
737 : return icode;
738 : }
739 :
740 : /* If MODE is not VOIDmode, return true if vec_gather_load is available for
741 : that mode. If MODE is VOIDmode, return true if gather_load is available
742 : for at least one vector mode.
743 : In that case, and if ELSVALS is nonzero, store the supported else values
744 : into the vector it points to. */
745 :
746 : bool
747 267399 : supports_vec_gather_load_p (machine_mode mode, vec<int> *elsvals)
748 : {
749 267399 : enum insn_code icode = CODE_FOR_nothing;
750 267399 : if (!this_fn_optabs->supports_vec_gather_load[mode] || elsvals)
751 : {
752 : /* Try the masked variants first. In case we later decide that we
753 : need a mask after all (thus requiring an else operand) we need
754 : to query it below and we cannot do that when using the
755 : non-masked optab. */
756 51314 : icode = supported_vec_convert_optab (mask_gather_load_optab, mode);
757 51314 : if (icode == CODE_FOR_nothing)
758 51314 : icode = supported_vec_convert_optab (mask_len_gather_load_optab, mode);
759 51314 : if (icode == CODE_FOR_nothing)
760 51314 : icode = supported_vec_convert_optab (gather_load_optab, mode);
761 102628 : this_fn_optabs->supports_vec_gather_load[mode]
762 102628 : = (icode != CODE_FOR_nothing) ? 1 : -1;
763 : }
764 :
765 267399 : if (elsvals && icode != CODE_FOR_nothing)
766 0 : get_supported_else_vals
767 0 : (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD), *elsvals);
768 :
769 267399 : return this_fn_optabs->supports_vec_gather_load[mode] > 0;
770 : }
771 :
772 : /* If MODE is not VOIDmode, return true if vec_scatter_store is available for
773 : that mode. If MODE is VOIDmode, return true if scatter_store is available
774 : for at least one vector mode. */
775 :
776 : bool
777 87065 : supports_vec_scatter_store_p (machine_mode mode)
778 : {
779 87065 : enum insn_code icode;
780 87065 : if (!this_fn_optabs->supports_vec_scatter_store[mode])
781 : {
782 7948 : icode = supported_vec_convert_optab (scatter_store_optab, mode);
783 7948 : if (icode == CODE_FOR_nothing)
784 7948 : icode = supported_vec_convert_optab (mask_scatter_store_optab, mode);
785 7948 : if (icode == CODE_FOR_nothing)
786 7948 : icode = supported_vec_convert_optab (mask_len_scatter_store_optab,
787 : mode);
788 15896 : this_fn_optabs->supports_vec_scatter_store[mode]
789 7948 : = (icode != CODE_FOR_nothing) ? 1 : -1;
790 : }
791 :
792 87065 : return this_fn_optabs->supports_vec_scatter_store[mode] > 0;
793 : }
794 :
795 : /* Whether we can extract part of the vector mode MODE as
796 : (scalar or vector) mode EXTR_MODE. */
797 :
798 : bool
799 4279 : can_vec_extract (machine_mode mode, machine_mode extr_mode)
800 : {
801 4279 : unsigned m;
802 2616 : if (!VECTOR_MODE_P (mode)
803 8558 : || !constant_multiple_p (GET_MODE_SIZE (mode),
804 4275 : GET_MODE_SIZE (extr_mode), &m))
805 : return false;
806 :
807 4275 : if (convert_optab_handler (vec_extract_optab, mode, extr_mode)
808 : != CODE_FOR_nothing)
809 : return true;
810 :
811 : /* Besides a direct vec_extract we can also use an element extract from
812 : an integer vector mode with elements of the size of the extr_mode. */
813 1694 : scalar_int_mode imode;
814 1694 : machine_mode vmode;
815 3388 : if (!int_mode_for_size (GET_MODE_BITSIZE (extr_mode), 0).exists (&imode)
816 3388 : || !related_vector_mode (mode, imode, m).exists (&vmode)
817 1694 : || (convert_optab_handler (vec_extract_optab, vmode, imode)
818 : == CODE_FOR_nothing))
819 0 : return false;
820 : /* We assume we can pun mode to vmode and imode to extr_mode. */
821 : return true;
822 : }
823 :
824 : /* OP is either neg_optab or abs_optab and FMODE is the floating-point inner
825 : mode of MODE. Check whether we can implement OP for mode MODE by using
826 : xor_optab to flip the sign bit (for neg_optab) or and_optab to clear the
827 : sign bit (for abs_optab). If so, return the integral mode that should be
828 : used to do the operation and set *BITPOS to the index of the sign bit
829 : (counting from the lsb). */
830 :
831 : opt_machine_mode
832 1268 : get_absneg_bit_mode (optab op, machine_mode mode,
833 : scalar_float_mode fmode, int *bitpos)
834 : {
835 : /* The format has to have a simple sign bit. */
836 1268 : auto fmt = REAL_MODE_FORMAT (fmode);
837 1268 : if (fmt == NULL)
838 0 : return {};
839 :
840 1268 : *bitpos = fmt->signbit_rw;
841 1268 : if (*bitpos < 0)
842 0 : return {};
843 :
844 : /* Don't create negative zeros if the format doesn't support them. */
845 1268 : if (op == neg_optab && !fmt->has_signed_zero)
846 0 : return {};
847 :
848 1268 : if (VECTOR_MODE_P (mode))
849 3 : return related_int_vector_mode (mode);
850 :
851 2580 : if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
852 2496 : return int_mode_for_mode (fmode);
853 :
854 17 : return word_mode;
855 : }
856 :
857 : /* Return true if we can implement OP for mode MODE directly, without resorting
858 : to a libfunc. This usually means that OP will be implemented inline.
859 :
860 : Note that this function cannot tell whether the target pattern chooses to
861 : use libfuncs internally. */
862 :
863 : bool
864 8005009 : can_open_code_p (optab op, machine_mode mode)
865 : {
866 8005009 : if (optab_handler (op, mode) != CODE_FOR_nothing)
867 : return true;
868 :
869 2374688 : if (op == umul_highpart_optab)
870 995 : return can_mult_highpart_p (mode, true);
871 :
872 2373693 : if (op == smul_highpart_optab)
873 1604 : return can_mult_highpart_p (mode, false);
874 :
875 2372089 : machine_mode new_mode;
876 2372089 : scalar_float_mode fmode;
877 2372089 : int bitpos;
878 2372089 : if ((op == neg_optab || op == abs_optab)
879 2676 : && is_a<scalar_float_mode> (GET_MODE_INNER (mode), &fmode)
880 4 : && get_absneg_bit_mode (op, mode, fmode, &bitpos).exists (&new_mode)
881 2372090 : && can_open_code_p (op == neg_optab ? xor_optab : and_optab, new_mode))
882 1 : return true;
883 :
884 2372088 : scalar_int_mode int_mode;
885 2372088 : if (op == bswap_optab && is_a<scalar_int_mode> (mode, &int_mode))
886 : {
887 : /* widen_bswap_or_bitreverse can implement smaller bswaps using
888 : wider bswaps and a shift. */
889 138864 : opt_scalar_int_mode wider_mode_iter;
890 555456 : FOR_EACH_WIDER_MODE (wider_mode_iter, int_mode)
891 416592 : if (optab_handler (op, wider_mode_iter.require ()) != CODE_FOR_nothing)
892 138864 : return true;
893 :
894 : /* expand_doubleword_bswap_or_bitreverse can use 2 word bswaps to
895 : implement a doubleword bswap. */
896 277728 : if (GET_MODE_SIZE (int_mode) == 2 * UNITS_PER_WORD
897 138864 : && optab_handler (op, word_mode) != CODE_FOR_nothing)
898 : return true;
899 : }
900 :
901 : return false;
902 : }
903 :
904 : /* Return true if we can implement OP for mode MODE in some way, either by
905 : open-coding it or by calling a libfunc. */
906 :
907 : bool
908 6229352 : can_implement_p (optab op, machine_mode mode)
909 : {
910 6229352 : return can_open_code_p (op, mode) || optab_libfunc (op, mode);
911 : }
|