Branch data Line data Source code
1 : : /* IR-agnostic target query functions relating to optabs
2 : : Copyright (C) 1987-2024 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 : 5612 : convert_optab_handler (convert_optab optab, machine_mode to_mode,
48 : : machine_mode from_mode, optimization_type opt_type)
49 : : {
50 : 5612 : insn_code icode = convert_optab_handler (optab, to_mode, from_mode);
51 : 5612 : if (icode == CODE_FOR_nothing
52 : 5612 : || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type))
53 : 5030 : 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 : 4825254 : direct_optab_handler (convert_optab optab, machine_mode mode,
63 : : optimization_type opt_type)
64 : : {
65 : 4825254 : insn_code icode = direct_optab_handler (optab, mode);
66 : 4825254 : if (icode == CODE_FOR_nothing
67 : 4825254 : || !targetm.optab_supported_p (optab, mode, mode, opt_type))
68 : 4622313 : 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 : 3393738 : 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 : 3393738 : direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
132 : 3393738 : enum insn_code icode = direct_optab_handler (optab, mode);
133 : 3393738 : if (icode == CODE_FOR_nothing)
134 : : return false;
135 : :
136 : 1494730 : const struct insn_data_d *data = &insn_data[icode];
137 : :
138 : 1494730 : machine_mode pos_mode = data->operand[pos_op].mode;
139 : 1494730 : if (pos_mode == VOIDmode)
140 : 0 : pos_mode = word_mode;
141 : :
142 : 1494730 : insn->icode = icode;
143 : 1494730 : insn->field_mode = as_a <scalar_int_mode> (mode);
144 : 1494730 : if (type == ET_unaligned_mem)
145 : 0 : insn->struct_mode = opt_scalar_int_mode ();
146 : : else
147 : 1494730 : insn->struct_mode = insn->field_mode;
148 : 1494730 : insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
149 : 1494730 : 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 : 3393738 : get_extraction_insn (extraction_insn *insn,
158 : : enum extraction_pattern pattern,
159 : : enum extraction_type type,
160 : : machine_mode mode)
161 : : {
162 : 3393738 : switch (pattern)
163 : : {
164 : 545496 : case EP_insv:
165 : 545496 : if (targetm.have_insv ()
166 : 545496 : && get_traditional_extraction_insn (insn, type, mode,
167 : : targetm.code_for_insv, 0, 3))
168 : : return true;
169 : 545496 : return get_optab_extraction_insn (insn, type, mode, insv_optab,
170 : 545496 : insvmisalign_optab, 2);
171 : :
172 : 734261 : case EP_extv:
173 : 734261 : if (targetm.have_extv ()
174 : 734261 : && get_traditional_extraction_insn (insn, type, mode,
175 : : targetm.code_for_extv, 1, 0))
176 : : return true;
177 : 734261 : return get_optab_extraction_insn (insn, type, mode, extv_optab,
178 : 734261 : extvmisalign_optab, 3);
179 : :
180 : 2113981 : case EP_extzv:
181 : 2113981 : if (targetm.have_extzv ()
182 : 2113981 : && get_traditional_extraction_insn (insn, type, mode,
183 : : targetm.code_for_extzv, 1, 0))
184 : : return true;
185 : 2113981 : return get_optab_extraction_insn (insn, type, mode, extzv_optab,
186 : 2113981 : 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 : 1817224 : 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 : 1817224 : opt_scalar_int_mode mode_iter;
211 : :
212 : 3716232 : FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
213 : : {
214 : 3393738 : scalar_int_mode mode = mode_iter.require ();
215 : 3393738 : if (get_extraction_insn (insn, pattern, type, mode))
216 : : {
217 : 1494730 : FOR_EACH_MODE_FROM (mode_iter, mode)
218 : : {
219 : 1494730 : mode = mode_iter.require ();
220 : 2989460 : if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
221 : 1494730 : || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
222 : : field_mode))
223 : : break;
224 : 0 : get_extraction_insn (insn, pattern, type, mode);
225 : : }
226 : 1494730 : 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 : 1610832 : 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 : 1610832 : return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
249 : 1610832 : 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 : 206392 : 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 : 206392 : unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
268 : 206392 : + bitsize
269 : 206392 : + BITS_PER_UNIT - 1);
270 : 206392 : struct_bits -= struct_bits % BITS_PER_UNIT;
271 : 206392 : return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
272 : 206392 : 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 : 5153755 : can_extend_p (machine_mode to_mode, machine_mode from_mode,
281 : : int unsignedp)
282 : : {
283 : 5153755 : if (unsignedp < 0 && targetm.have_ptr_extend ())
284 : 0 : return targetm.code_for_ptr_extend;
285 : :
286 : 5153755 : convert_optab tab = unsignedp ? zext_optab : sext_optab;
287 : 5153755 : 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 : 363361 : can_float_p (machine_mode fltmode, machine_mode fixmode,
296 : : int unsignedp)
297 : : {
298 : 363361 : convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
299 : 363361 : 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 : 250579 : can_fix_p (machine_mode fixmode, machine_mode fltmode,
311 : : int unsignedp, bool *truncp_ptr)
312 : : {
313 : 250579 : convert_optab tab;
314 : 250579 : enum insn_code icode;
315 : :
316 : 250579 : tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
317 : 250579 : icode = convert_optab_handler (tab, fixmode, fltmode);
318 : 250579 : if (icode != CODE_FOR_nothing)
319 : : {
320 : 50392 : *truncp_ptr = false;
321 : 50392 : 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 : 200187 : tab = unsignedp ? ufix_optab : sfix_optab;
328 : 200187 : icode = convert_optab_handler (tab, fixmode, fltmode);
329 : 200187 : if (icode != CODE_FOR_nothing
330 : 200187 : && 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 : 1219111 : can_conditionally_move_p (machine_mode mode)
349 : : {
350 : 1219111 : 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 : 712550 : qimode_for_vec_perm (machine_mode mode)
360 : : {
361 : 1425100 : if (GET_MODE_INNER (mode) != QImode)
362 : 1340406 : return related_vector_mode (mode, QImode, GET_MODE_SIZE (mode));
363 : 42347 : return opt_machine_mode ();
364 : : }
365 : :
366 : : /* Return true if selector SEL can be represented in the integer
367 : : equivalent of vector mode MODE. */
368 : :
369 : : bool
370 : 1351718 : selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel)
371 : : {
372 : 1351718 : unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode));
373 : 1351718 : return (mask == HOST_WIDE_INT_M1U
374 : 1351718 : || sel.all_in_range_p (0, mask + 1));
375 : : }
376 : :
377 : : /* Return true if VEC_PERM_EXPRs with variable selector operands can be
378 : : expanded using SIMD extensions of the CPU. MODE is the mode of the
379 : : vectors being permuted. */
380 : :
381 : : bool
382 : 862 : can_vec_perm_var_p (machine_mode mode)
383 : : {
384 : : /* If the target doesn't implement a vector mode for the vector type,
385 : : then no operations are supported. */
386 : 862 : if (!VECTOR_MODE_P (mode))
387 : : return false;
388 : :
389 : 611 : if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
390 : : return true;
391 : :
392 : : /* We allow fallback to a QI vector mode, and adjust the mask. */
393 : 600 : machine_mode qimode;
394 : 600 : if (!qimode_for_vec_perm (mode).exists (&qimode)
395 : 968 : || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1))
396 : 116 : return false;
397 : :
398 : 484 : if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
399 : : return false;
400 : :
401 : : /* In order to support the lowering of variable permutations,
402 : : we need to support shifts and adds. */
403 : 0 : if (GET_MODE_UNIT_SIZE (mode) > 2
404 : 0 : && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
405 : 0 : && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
406 : : return false;
407 : 0 : if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
408 : : return false;
409 : :
410 : : return true;
411 : : }
412 : :
413 : : /* Return true if the target directly supports VEC_PERM_EXPRs on vectors
414 : : of mode OP_MODE and result vector of mode MODE using the selector SEL.
415 : : ALLOW_VARIABLE_P is true if it is acceptable to force the selector into a
416 : : register and use a variable permute (if the target supports that).
417 : :
418 : : Note that additional permutations representing whole-vector shifts may
419 : : also be handled via the vec_shr or vec_shl optab, but only where the
420 : : second input vector is entirely constant zeroes; this case is not dealt
421 : : with here. */
422 : :
423 : : bool
424 : 783049 : can_vec_perm_const_p (machine_mode mode, machine_mode op_mode,
425 : : const vec_perm_indices &sel, bool allow_variable_p)
426 : : {
427 : : /* If the target doesn't implement a vector mode for the vector type,
428 : : then no operations are supported. */
429 : 783049 : if (!VECTOR_MODE_P (mode))
430 : : return false;
431 : :
432 : : /* It's probably cheaper to test for the variable case first. */
433 : 781027 : if (op_mode == mode && allow_variable_p && selector_fits_mode_p (mode, sel))
434 : : {
435 : 738946 : if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
436 : 783049 : return true;
437 : :
438 : : /* Unlike can_vec_perm_var_p, we don't need to test for optabs
439 : : related computing the QImode selector, since that happens at
440 : : compile time. */
441 : 648440 : machine_mode qimode;
442 : 648440 : if (qimode_for_vec_perm (mode).exists (&qimode))
443 : : {
444 : 612772 : vec_perm_indices qimode_indices;
445 : 1225544 : qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode));
446 : 612772 : if (selector_fits_mode_p (qimode, qimode_indices)
447 : 612772 : && (direct_optab_handler (vec_perm_optab, qimode)
448 : : != CODE_FOR_nothing))
449 : 18 : return true;
450 : 612772 : }
451 : : }
452 : :
453 : 690503 : if (targetm.vectorize.vec_perm_const != NULL)
454 : : {
455 : 690503 : if (targetm.vectorize.vec_perm_const (mode, op_mode, NULL_RTX, NULL_RTX,
456 : : NULL_RTX, sel))
457 : : return true;
458 : :
459 : : /* ??? For completeness, we ought to check the QImode version of
460 : : vec_perm_const_optab. But all users of this implicit lowering
461 : : feature implement the variable vec_perm_optab, and the ia64
462 : : port specifically doesn't want us to lower V2SF operations
463 : : into integer operations. */
464 : : }
465 : :
466 : : return false;
467 : : }
468 : :
469 : : /* Find a widening optab even if it doesn't widen as much as we want.
470 : : E.g. if from_mode is HImode, and to_mode is DImode, and there is no
471 : : direct HI->SI insn, then return SI->DI, if that exists. */
472 : :
473 : : enum insn_code
474 : 282895 : find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
475 : : machine_mode from_mode,
476 : : machine_mode *found_mode)
477 : : {
478 : 282895 : machine_mode limit_mode = to_mode;
479 : 282895 : if (is_a <scalar_int_mode> (from_mode))
480 : : {
481 : 282405 : gcc_checking_assert (is_a <scalar_int_mode> (to_mode)
482 : : && known_lt (GET_MODE_PRECISION (from_mode),
483 : : GET_MODE_PRECISION (to_mode)));
484 : : /* The modes after FROM_MODE are all MODE_INT, so the only
485 : : MODE_PARTIAL_INT mode we consider is FROM_MODE itself.
486 : : If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing
487 : : MODE_INT. */
488 : 282405 : if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT)
489 : 0 : limit_mode = GET_MODE_WIDER_MODE (limit_mode).require ();
490 : : }
491 : 490 : else if (is_a <scalar_int_mode> (to_mode))
492 : : {
493 : 0 : gcc_checking_assert (VECTOR_MODE_P (from_mode)
494 : : && GET_MODE_INNER (from_mode) < to_mode);
495 : : limit_mode = from_mode;
496 : : }
497 : : else
498 : 490 : gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
499 : : && from_mode < to_mode);
500 : 527297 : FOR_EACH_MODE (from_mode, from_mode, limit_mode)
501 : : {
502 : 301412 : enum insn_code handler = convert_optab_handler (op, to_mode, from_mode);
503 : :
504 : 301412 : if (handler != CODE_FOR_nothing)
505 : : {
506 : 57010 : if (found_mode)
507 : 10209 : *found_mode = from_mode;
508 : 57010 : return handler;
509 : : }
510 : : }
511 : :
512 : : return CODE_FOR_nothing;
513 : : }
514 : :
515 : : /* Return non-zero if a highpart multiply is supported or can be synthesized.
516 : : For the benefit of expand_mult_highpart, the return value is 1 for direct,
517 : : 2 for integral widening, 3 for even/odd widening, 4 for hi/lo widening. */
518 : :
519 : : int
520 : 88609 : can_mult_highpart_p (machine_mode mode, bool uns_p)
521 : : {
522 : 88609 : optab op;
523 : 88609 : scalar_int_mode int_mode, wider_mode;
524 : :
525 : 88609 : op = uns_p ? umul_highpart_optab : smul_highpart_optab;
526 : 88609 : if (optab_handler (op, mode) != CODE_FOR_nothing)
527 : : return 1;
528 : :
529 : : /* If the mode is integral, synth from widening or larger operations. */
530 : 83315 : if (is_a <scalar_int_mode> (mode, &int_mode)
531 : 4781 : && GET_MODE_WIDER_MODE (int_mode).exists (&wider_mode))
532 : : {
533 : 4781 : op = uns_p ? umul_widen_optab : smul_widen_optab;
534 : 4781 : if (convert_optab_handler (op, wider_mode, mode) != CODE_FOR_nothing)
535 : : return 2;
536 : :
537 : : /* The test on the size comes from expmed_mult_highpart_optab. */
538 : 4781 : if (optab_handler (smul_optab, wider_mode) != CODE_FOR_nothing
539 : 4781 : && GET_MODE_BITSIZE (int_mode) - 1 < BITS_PER_WORD)
540 : : return 2;
541 : : }
542 : :
543 : : /* If the mode is an integral vector, synth from widening operations. */
544 : 83315 : if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
545 : : return 0;
546 : :
547 : 157068 : poly_int64 nunits = GET_MODE_NUNITS (mode);
548 : :
549 : 78534 : op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
550 : 78534 : if (optab_handler (op, mode) != CODE_FOR_nothing)
551 : : {
552 : 21106 : op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
553 : 21106 : if (optab_handler (op, mode) != CODE_FOR_nothing)
554 : : {
555 : : /* The encoding has 2 interleaved stepped patterns. */
556 : 21106 : vec_perm_builder sel (nunits, 2, 3);
557 : 147742 : for (unsigned int i = 0; i < 6; ++i)
558 : 253272 : sel.quick_push (!BYTES_BIG_ENDIAN
559 : 126636 : + (i & ~1)
560 : 126636 : + ((i & 1) ? nunits : 0));
561 : 21106 : vec_perm_indices indices (sel, 2, nunits);
562 : 21106 : if (can_vec_perm_const_p (mode, mode, indices))
563 : 21106 : return 3;
564 : 21106 : }
565 : : }
566 : :
567 : 57428 : op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
568 : 57428 : if (optab_handler (op, mode) != CODE_FOR_nothing)
569 : : {
570 : 334 : op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
571 : 334 : if (optab_handler (op, mode) != CODE_FOR_nothing)
572 : : {
573 : : /* The encoding has a single stepped pattern. */
574 : 334 : vec_perm_builder sel (nunits, 1, 3);
575 : 1336 : for (unsigned int i = 0; i < 3; ++i)
576 : 1002 : sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
577 : 334 : vec_perm_indices indices (sel, 2, nunits);
578 : 334 : if (can_vec_perm_const_p (mode, mode, indices))
579 : 334 : return 4;
580 : 334 : }
581 : : }
582 : :
583 : : return 0;
584 : : }
585 : :
586 : : /* Return true if there is a compare_and_swap pattern. */
587 : :
588 : : bool
589 : 97264 : can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
590 : : {
591 : 97264 : enum insn_code icode;
592 : :
593 : : /* Check for __atomic_compare_and_swap. */
594 : 97264 : icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
595 : 97264 : if (icode != CODE_FOR_nothing)
596 : : return true;
597 : :
598 : : /* Check for __sync_compare_and_swap. */
599 : 130 : icode = optab_handler (sync_compare_and_swap_optab, mode);
600 : 130 : if (icode != CODE_FOR_nothing)
601 : : return true;
602 : 130 : if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
603 : : return true;
604 : :
605 : : /* No inline compare and swap. */
606 : : return false;
607 : : }
608 : :
609 : : /* Return true if an atomic exchange can be performed. */
610 : :
611 : : bool
612 : 88 : can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
613 : : {
614 : 88 : enum insn_code icode;
615 : :
616 : : /* Check for __atomic_exchange. */
617 : 88 : icode = direct_optab_handler (atomic_exchange_optab, mode);
618 : 88 : if (icode != CODE_FOR_nothing)
619 : : return true;
620 : :
621 : : /* Don't check __sync_test_and_set, as on some platforms that
622 : : has reduced functionality. Targets that really do support
623 : : a proper exchange should simply be updated to the __atomics. */
624 : :
625 : 0 : return can_compare_and_swap_p (mode, allow_libcall);
626 : : }
627 : :
628 : : /* Return true if an atomic load can be performed without falling back to
629 : : a compare-and-swap. */
630 : :
631 : : bool
632 : 152452 : can_atomic_load_p (machine_mode mode)
633 : : {
634 : 152452 : enum insn_code icode;
635 : :
636 : : /* Does the target supports the load directly? */
637 : 152452 : icode = direct_optab_handler (atomic_load_optab, mode);
638 : 152452 : if (icode != CODE_FOR_nothing)
639 : : return true;
640 : :
641 : : /* If the size of the object is greater than word size on this target,
642 : : then we assume that a load will not be atomic. Also see
643 : : expand_atomic_load. */
644 : 4046 : return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD);
645 : : }
646 : :
647 : : /* Determine whether "1 << x" is relatively cheap in word_mode. */
648 : :
649 : : bool
650 : 1036976 : lshift_cheap_p (bool speed_p)
651 : : {
652 : : /* FIXME: This should be made target dependent via this "this_target"
653 : : mechanism, similar to e.g. can_copy_init_p in gcse.cc. */
654 : 1036976 : static bool init[2] = { false, false };
655 : 1036976 : static bool cheap[2] = { true, true };
656 : :
657 : : /* If the targer has no lshift in word_mode, the operation will most
658 : : probably not be cheap. ??? Does GCC even work for such targets? */
659 : 1036976 : if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
660 : : return false;
661 : :
662 : 1036976 : if (!init[speed_p])
663 : : {
664 : 39160 : rtx reg = gen_raw_REG (word_mode, 10000);
665 : 39160 : int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
666 : : word_mode, speed_p);
667 : 39160 : cheap[speed_p] = cost < COSTS_N_INSNS (3);
668 : 39160 : init[speed_p] = true;
669 : : }
670 : :
671 : 1036976 : return cheap[speed_p];
672 : : }
673 : :
674 : : /* If MODE is not VOIDmode, return true if vector conversion optab OP supports
675 : : that mode, given that the second mode is always an integer vector.
676 : : If MODE is VOIDmode, return true if OP supports any vector mode. */
677 : :
678 : : static enum insn_code
679 : 100221 : supported_vec_convert_optab (optab op, machine_mode mode)
680 : : {
681 : 100221 : int start = mode == VOIDmode ? 0 : mode;
682 : 100221 : int end = mode == VOIDmode ? MAX_MACHINE_MODE - 1 : mode;
683 : 100221 : enum insn_code icode = CODE_FOR_nothing;
684 : 200442 : for (int i = start; i <= end; ++i)
685 : 100221 : if (VECTOR_MODE_P ((machine_mode) i))
686 : 3207072 : for (int j = MIN_MODE_VECTOR_INT; j < MAX_MODE_VECTOR_INT; ++j)
687 : : {
688 : 6213702 : if ((icode
689 : 3106851 : = convert_optab_handler (op, (machine_mode) i,
690 : : (machine_mode) j)) != CODE_FOR_nothing)
691 : : return icode;
692 : : }
693 : :
694 : : return icode;
695 : : }
696 : :
697 : : /* If MODE is not VOIDmode, return true if vec_gather_load is available for
698 : : that mode. If MODE is VOIDmode, return true if gather_load is available
699 : : for at least one vector mode.
700 : : In that case, and if ELSVALS is nonzero, store the supported else values
701 : : into the vector it points to. */
702 : :
703 : : bool
704 : 90361 : supports_vec_gather_load_p (machine_mode mode, vec<int> *elsvals)
705 : : {
706 : 90361 : enum insn_code icode = CODE_FOR_nothing;
707 : 90361 : if (!this_fn_optabs->supports_vec_gather_load[mode] || elsvals)
708 : : {
709 : : /* Try the masked variants first. In case we later decide that we
710 : : need a mask after all (thus requiring an else operand) we need
711 : : to query it below and we cannot do that when using the
712 : : non-masked optab. */
713 : 26837 : icode = supported_vec_convert_optab (mask_gather_load_optab, mode);
714 : 26837 : if (icode == CODE_FOR_nothing)
715 : 26837 : icode = supported_vec_convert_optab (mask_len_gather_load_optab, mode);
716 : 26837 : if (icode == CODE_FOR_nothing)
717 : 26837 : icode = supported_vec_convert_optab (gather_load_optab, mode);
718 : 53674 : this_fn_optabs->supports_vec_gather_load[mode]
719 : 53674 : = (icode != CODE_FOR_nothing) ? 1 : -1;
720 : : }
721 : :
722 : : /* For gather the optab's operand indices do not match the IFN's because
723 : : the latter does not have the extension operand (operand 3). It is
724 : : implicitly added during expansion so we use the IFN's else index + 1.
725 : : */
726 : 90361 : if (elsvals && icode != CODE_FOR_nothing)
727 : 0 : get_supported_else_vals
728 : 0 : (icode, internal_fn_else_index (IFN_MASK_GATHER_LOAD) + 1, *elsvals);
729 : :
730 : 90361 : return this_fn_optabs->supports_vec_gather_load[mode] > 0;
731 : : }
732 : :
733 : : /* If MODE is not VOIDmode, return true if vec_scatter_store is available for
734 : : that mode. If MODE is VOIDmode, return true if scatter_store is available
735 : : for at least one vector mode. */
736 : :
737 : : bool
738 : 69431 : supports_vec_scatter_store_p (machine_mode mode)
739 : : {
740 : 69431 : enum insn_code icode;
741 : 69431 : if (!this_fn_optabs->supports_vec_scatter_store[mode])
742 : : {
743 : 6570 : icode = supported_vec_convert_optab (scatter_store_optab, mode);
744 : 6570 : if (icode == CODE_FOR_nothing)
745 : 6570 : icode = supported_vec_convert_optab (mask_scatter_store_optab, mode);
746 : 6570 : if (icode == CODE_FOR_nothing)
747 : 6570 : icode = supported_vec_convert_optab (mask_len_scatter_store_optab,
748 : : mode);
749 : 13140 : this_fn_optabs->supports_vec_scatter_store[mode]
750 : 6570 : = (icode != CODE_FOR_nothing) ? 1 : -1;
751 : : }
752 : :
753 : 69431 : return this_fn_optabs->supports_vec_scatter_store[mode] > 0;
754 : : }
755 : :
756 : : /* Whether we can extract part of the vector mode MODE as
757 : : (scalar or vector) mode EXTR_MODE. */
758 : :
759 : : bool
760 : 4074 : can_vec_extract (machine_mode mode, machine_mode extr_mode)
761 : : {
762 : 4074 : unsigned m;
763 : 2406 : if (!VECTOR_MODE_P (mode)
764 : 8148 : || !constant_multiple_p (GET_MODE_SIZE (mode),
765 : 4074 : GET_MODE_SIZE (extr_mode), &m))
766 : : return false;
767 : :
768 : 4074 : if (convert_optab_handler (vec_extract_optab, mode, extr_mode)
769 : : != CODE_FOR_nothing)
770 : : return true;
771 : :
772 : : /* Besides a direct vec_extract we can also use an element extract from
773 : : an integer vector mode with elements of the size of the extr_mode. */
774 : 1504 : scalar_int_mode imode;
775 : 1504 : machine_mode vmode;
776 : 3008 : if (!int_mode_for_size (GET_MODE_BITSIZE (extr_mode), 0).exists (&imode)
777 : 3008 : || !related_vector_mode (mode, imode, m).exists (&vmode)
778 : 1504 : || (convert_optab_handler (vec_extract_optab, vmode, imode)
779 : : == CODE_FOR_nothing))
780 : 0 : return false;
781 : : /* We assume we can pun mode to vmode and imode to extr_mode. */
782 : : return true;
783 : : }
784 : :
785 : : /* OP is either neg_optab or abs_optab and FMODE is the floating-point inner
786 : : mode of MODE. Check whether we can implement OP for mode MODE by using
787 : : xor_optab to flip the sign bit (for neg_optab) or and_optab to clear the
788 : : sign bit (for abs_optab). If so, return the integral mode that should be
789 : : used to do the operation and set *BITPOS to the index of the sign bit
790 : : (counting from the lsb). */
791 : :
792 : : opt_machine_mode
793 : 55 : get_absneg_bit_mode (optab op, machine_mode mode,
794 : : scalar_float_mode fmode, int *bitpos)
795 : : {
796 : : /* The format has to have a simple sign bit. */
797 : 55 : auto fmt = REAL_MODE_FORMAT (fmode);
798 : 55 : if (fmt == NULL)
799 : 0 : return {};
800 : :
801 : 55 : *bitpos = fmt->signbit_rw;
802 : 55 : if (*bitpos < 0)
803 : 0 : return {};
804 : :
805 : : /* Don't create negative zeros if the format doesn't support them. */
806 : 55 : if (op == neg_optab && !fmt->has_signed_zero)
807 : 0 : return {};
808 : :
809 : 55 : if (VECTOR_MODE_P (mode))
810 : 4 : return related_int_vector_mode (mode);
811 : :
812 : 102 : if (GET_MODE_SIZE (fmode) <= UNITS_PER_WORD)
813 : 68 : return int_mode_for_mode (fmode);
814 : :
815 : 17 : return word_mode;
816 : : }
817 : :
818 : : /* Return true if we can implement OP for mode MODE directly, without resorting
819 : : to a libfunc. This usually means that OP will be implemented inline.
820 : :
821 : : Note that this function cannot tell whether the target pattern chooses to
822 : : use libfuncs internally. */
823 : :
824 : : bool
825 : 4790122 : can_open_code_p (optab op, machine_mode mode)
826 : : {
827 : 4790122 : if (optab_handler (op, mode) != CODE_FOR_nothing)
828 : : return true;
829 : :
830 : 1771285 : if (op == umul_highpart_optab)
831 : 956 : return can_mult_highpart_p (mode, true);
832 : :
833 : 1770329 : if (op == smul_highpart_optab)
834 : 1372 : return can_mult_highpart_p (mode, false);
835 : :
836 : 1768957 : machine_mode new_mode;
837 : 1768957 : scalar_float_mode fmode;
838 : 1768957 : int bitpos;
839 : 1768957 : if ((op == neg_optab || op == abs_optab)
840 : 857 : && is_a<scalar_float_mode> (GET_MODE_INNER (mode), &fmode)
841 : 1768957 : && get_absneg_bit_mode (op, mode, fmode, &bitpos).exists (&new_mode)
842 : 1768958 : && can_implement_p (op == neg_optab ? xor_optab : and_optab, new_mode))
843 : 1 : return true;
844 : :
845 : : return false;
846 : : }
847 : :
848 : : /* Return true if we can implement OP for mode MODE in some way, either by
849 : : open-coding it or by calling a libfunc. */
850 : :
851 : : bool
852 : 4790122 : can_implement_p (optab op, machine_mode mode)
853 : : {
854 : 4790122 : return can_open_code_p (op, mode) || optab_libfunc (op, mode);
855 : : }
|