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