[19/77] Add a smallest_int_mode_for_size helper function
[official-gcc.git] / gcc / optabs-query.c
blob48b1250bda24fda4443aa2f1b343636c6092fc32
1 /* IR-agnostic target query functions relating to optabs
2 Copyright (C) 1987-2017 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
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
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. */
42 insn_code
43 convert_optab_handler (convert_optab optab, machine_mode to_mode,
44 machine_mode from_mode, optimization_type opt_type)
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;
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. */
57 insn_code
58 direct_optab_handler (convert_optab optab, machine_mode mode,
59 optimization_type opt_type)
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;
68 /* Enumerates the possible types of structure operand to an
69 extraction_insn. */
70 enum extraction_type { ET_unaligned_mem, ET_reg };
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). */
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)
86 const struct insn_data_d *data = &insn_data[icode];
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;
94 machine_mode field_mode = data->operand[field_op].mode;
95 if (field_mode == VOIDmode)
96 field_mode = word_mode;
98 machine_mode pos_mode = data->operand[struct_op + 2].mode;
99 if (pos_mode == VOIDmode)
100 pos_mode = word_mode;
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;
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.
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. */
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)
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;
127 const struct insn_data_d *data = &insn_data[icode];
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;
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. */
142 static bool
143 get_extraction_insn (extraction_insn *insn,
144 enum extraction_pattern pattern,
145 enum extraction_type type,
146 machine_mode mode)
148 switch (pattern)
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);
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);
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);
174 default:
175 gcc_unreachable ();
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.
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. */
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)
196 opt_scalar_int_mode mode_iter;
197 FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
199 scalar_int_mode mode = mode_iter.require ();
200 if (get_extraction_insn (insn, pattern, type, mode))
202 FOR_EACH_MODE_FROM (mode_iter, mode)
204 mode = mode_iter.require ();
205 if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (field_mode)
206 || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
207 field_mode))
208 break;
209 get_extraction_insn (insn, pattern, type, mode);
211 return true;
214 return false;
217 /* Return true if an instruction exists to access a field of mode
218 FIELDMODE in a register structure that has STRUCT_BITS significant bits.
219 Describe the "best" such instruction in *INSN if so. PATTERN describes
220 the type of insertion or extraction we want to perform.
222 For an insertion, the number of significant structure bits includes
223 all bits of the target. For an extraction, it need only include the
224 most significant bit of the field. Larger widths are acceptable
225 in both cases. */
227 bool
228 get_best_reg_extraction_insn (extraction_insn *insn,
229 enum extraction_pattern pattern,
230 unsigned HOST_WIDE_INT struct_bits,
231 machine_mode field_mode)
233 return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
234 field_mode);
237 /* Return true if an instruction exists to access a field of BITSIZE
238 bits starting BITNUM bits into a memory structure. Describe the
239 "best" such instruction in *INSN if so. PATTERN describes the type
240 of insertion or extraction we want to perform and FIELDMODE is the
241 natural mode of the extracted field.
243 The instructions considered here only access bytes that overlap
244 the bitfield; they do not touch any surrounding bytes. */
246 bool
247 get_best_mem_extraction_insn (extraction_insn *insn,
248 enum extraction_pattern pattern,
249 HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
250 machine_mode field_mode)
252 unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
253 + bitsize
254 + BITS_PER_UNIT - 1);
255 struct_bits -= struct_bits % BITS_PER_UNIT;
256 return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
257 struct_bits, field_mode);
260 /* Return the insn code used to extend FROM_MODE to TO_MODE.
261 UNSIGNEDP specifies zero-extension instead of sign-extension. If
262 no such operation exists, CODE_FOR_nothing will be returned. */
264 enum insn_code
265 can_extend_p (machine_mode to_mode, machine_mode from_mode,
266 int unsignedp)
268 if (unsignedp < 0 && targetm.have_ptr_extend ())
269 return targetm.code_for_ptr_extend;
271 convert_optab tab = unsignedp ? zext_optab : sext_optab;
272 return convert_optab_handler (tab, to_mode, from_mode);
275 /* Return the insn code to convert fixed-point mode FIXMODE to floating-point
276 mode FLTMODE, or CODE_FOR_nothing if no such instruction exists.
277 UNSIGNEDP specifies whether FIXMODE is unsigned. */
279 enum insn_code
280 can_float_p (machine_mode fltmode, machine_mode fixmode,
281 int unsignedp)
283 convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
284 return convert_optab_handler (tab, fltmode, fixmode);
287 /* Return the insn code to convert floating-point mode FLTMODE to fixed-point
288 mode FIXMODE, or CODE_FOR_nothing if no such instruction exists.
289 UNSIGNEDP specifies whether FIXMODE is unsigned.
291 On a successful return, set *TRUNCP_PTR to true if it is necessary to
292 output an explicit FTRUNC before the instruction. */
294 enum insn_code
295 can_fix_p (machine_mode fixmode, machine_mode fltmode,
296 int unsignedp, bool *truncp_ptr)
298 convert_optab tab;
299 enum insn_code icode;
301 tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
302 icode = convert_optab_handler (tab, fixmode, fltmode);
303 if (icode != CODE_FOR_nothing)
305 *truncp_ptr = false;
306 return icode;
309 /* FIXME: This requires a port to define both FIX and FTRUNC pattern
310 for this to work. We need to rework the fix* and ftrunc* patterns
311 and documentation. */
312 tab = unsignedp ? ufix_optab : sfix_optab;
313 icode = convert_optab_handler (tab, fixmode, fltmode);
314 if (icode != CODE_FOR_nothing
315 && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
317 *truncp_ptr = true;
318 return icode;
321 return CODE_FOR_nothing;
324 /* Return nonzero if a conditional move of mode MODE is supported.
326 This function is for combine so it can tell whether an insn that looks
327 like a conditional move is actually supported by the hardware. If we
328 guess wrong we lose a bit on optimization, but that's it. */
329 /* ??? sparc64 supports conditionally moving integers values based on fp
330 comparisons, and vice versa. How do we handle them? */
332 bool
333 can_conditionally_move_p (machine_mode mode)
335 return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing;
338 /* Return true if VEC_PERM_EXPR of arbitrary input vectors can be
339 expanded using SIMD extensions of the CPU. SEL may be NULL, which
340 stands for an unknown constant. Note that additional permutations
341 representing whole-vector shifts may also be handled via the vec_shr
342 optab, but only where the second input vector is entirely constant
343 zeroes; this case is not dealt with here. */
345 bool
346 can_vec_perm_p (machine_mode mode, bool variable,
347 const unsigned char *sel)
349 machine_mode qimode;
351 /* If the target doesn't implement a vector mode for the vector type,
352 then no operations are supported. */
353 if (!VECTOR_MODE_P (mode))
354 return false;
356 if (!variable)
358 if (direct_optab_handler (vec_perm_const_optab, mode) != CODE_FOR_nothing
359 && (sel == NULL
360 || targetm.vectorize.vec_perm_const_ok == NULL
361 || targetm.vectorize.vec_perm_const_ok (mode, sel)))
362 return true;
365 if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
366 return true;
368 /* We allow fallback to a QI vector mode, and adjust the mask. */
369 if (GET_MODE_INNER (mode) == QImode)
370 return false;
371 qimode = mode_for_vector (QImode, GET_MODE_SIZE (mode));
372 if (!VECTOR_MODE_P (qimode))
373 return false;
375 /* ??? For completeness, we ought to check the QImode version of
376 vec_perm_const_optab. But all users of this implicit lowering
377 feature implement the variable vec_perm_optab. */
378 if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
379 return false;
381 /* In order to support the lowering of variable permutations,
382 we need to support shifts and adds. */
383 if (variable)
385 if (GET_MODE_UNIT_SIZE (mode) > 2
386 && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
387 && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
388 return false;
389 if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
390 return false;
393 return true;
396 /* Like optab_handler, but for widening_operations that have a
397 TO_MODE and a FROM_MODE. */
399 enum insn_code
400 widening_optab_handler (optab op, machine_mode to_mode,
401 machine_mode from_mode)
403 unsigned scode = (op << 16) | to_mode;
404 if (to_mode != from_mode && from_mode != VOIDmode)
406 /* ??? Why does find_widening_optab_handler_and_mode attempt to
407 widen things that can't be widened? E.g. add_optab... */
408 if (op > LAST_CONV_OPTAB)
409 return CODE_FOR_nothing;
410 scode |= from_mode << 8;
412 return raw_optab_handler (scode);
415 /* Find a widening optab even if it doesn't widen as much as we want.
416 E.g. if from_mode is HImode, and to_mode is DImode, and there is no
417 direct HI->SI insn, then return SI->DI, if that exists.
418 If PERMIT_NON_WIDENING is non-zero then this can be used with
419 non-widening optabs also. */
421 enum insn_code
422 find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
423 machine_mode from_mode,
424 int permit_non_widening,
425 machine_mode *found_mode)
427 for (; (permit_non_widening || from_mode != to_mode)
428 && GET_MODE_SIZE (from_mode) <= GET_MODE_SIZE (to_mode)
429 && from_mode != VOIDmode;
430 from_mode = GET_MODE_WIDER_MODE (from_mode).else_void ())
432 enum insn_code handler = widening_optab_handler (op, to_mode,
433 from_mode);
435 if (handler != CODE_FOR_nothing)
437 if (found_mode)
438 *found_mode = from_mode;
439 return handler;
443 return CODE_FOR_nothing;
446 /* Return non-zero if a highpart multiply is supported of can be synthisized.
447 For the benefit of expand_mult_highpart, the return value is 1 for direct,
448 2 for even/odd widening, and 3 for hi/lo widening. */
451 can_mult_highpart_p (machine_mode mode, bool uns_p)
453 optab op;
454 unsigned char *sel;
455 unsigned i, nunits;
457 op = uns_p ? umul_highpart_optab : smul_highpart_optab;
458 if (optab_handler (op, mode) != CODE_FOR_nothing)
459 return 1;
461 /* If the mode is an integral vector, synth from widening operations. */
462 if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
463 return 0;
465 nunits = GET_MODE_NUNITS (mode);
466 sel = XALLOCAVEC (unsigned char, nunits);
468 op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
469 if (optab_handler (op, mode) != CODE_FOR_nothing)
471 op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
472 if (optab_handler (op, mode) != CODE_FOR_nothing)
474 for (i = 0; i < nunits; ++i)
475 sel[i] = !BYTES_BIG_ENDIAN + (i & ~1) + ((i & 1) ? nunits : 0);
476 if (can_vec_perm_p (mode, false, sel))
477 return 2;
481 op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
482 if (optab_handler (op, mode) != CODE_FOR_nothing)
484 op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
485 if (optab_handler (op, mode) != CODE_FOR_nothing)
487 for (i = 0; i < nunits; ++i)
488 sel[i] = 2 * i + (BYTES_BIG_ENDIAN ? 0 : 1);
489 if (can_vec_perm_p (mode, false, sel))
490 return 3;
494 return 0;
497 /* Return true if target supports vector masked load/store for mode. */
499 bool
500 can_vec_mask_load_store_p (machine_mode mode,
501 machine_mode mask_mode,
502 bool is_load)
504 optab op = is_load ? maskload_optab : maskstore_optab;
505 machine_mode vmode;
506 unsigned int vector_sizes;
508 /* If mode is vector mode, check it directly. */
509 if (VECTOR_MODE_P (mode))
510 return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing;
512 /* Otherwise, return true if there is some vector mode with
513 the mask load/store supported. */
515 /* See if there is any chance the mask load or store might be
516 vectorized. If not, punt. */
517 vmode = targetm.vectorize.preferred_simd_mode (mode);
518 if (!VECTOR_MODE_P (vmode))
519 return false;
521 mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
522 GET_MODE_SIZE (vmode));
523 if (mask_mode == VOIDmode)
524 return false;
526 if (convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
527 return true;
529 vector_sizes = targetm.vectorize.autovectorize_vector_sizes ();
530 while (vector_sizes != 0)
532 unsigned int cur = 1 << floor_log2 (vector_sizes);
533 vector_sizes &= ~cur;
534 if (cur <= GET_MODE_SIZE (mode))
535 continue;
536 vmode = mode_for_vector (mode, cur / GET_MODE_SIZE (mode));
537 mask_mode = targetm.vectorize.get_mask_mode (GET_MODE_NUNITS (vmode),
538 cur);
539 if (VECTOR_MODE_P (vmode)
540 && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
541 return true;
543 return false;
546 /* Return true if there is a compare_and_swap pattern. */
548 bool
549 can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
551 enum insn_code icode;
553 /* Check for __atomic_compare_and_swap. */
554 icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
555 if (icode != CODE_FOR_nothing)
556 return true;
558 /* Check for __sync_compare_and_swap. */
559 icode = optab_handler (sync_compare_and_swap_optab, mode);
560 if (icode != CODE_FOR_nothing)
561 return true;
562 if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
563 return true;
565 /* No inline compare and swap. */
566 return false;
569 /* Return true if an atomic exchange can be performed. */
571 bool
572 can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
574 enum insn_code icode;
576 /* Check for __atomic_exchange. */
577 icode = direct_optab_handler (atomic_exchange_optab, mode);
578 if (icode != CODE_FOR_nothing)
579 return true;
581 /* Don't check __sync_test_and_set, as on some platforms that
582 has reduced functionality. Targets that really do support
583 a proper exchange should simply be updated to the __atomics. */
585 return can_compare_and_swap_p (mode, allow_libcall);
588 /* Return true if an atomic load can be performed without falling back to
589 a compare-and-swap. */
591 bool
592 can_atomic_load_p (machine_mode mode)
594 enum insn_code icode;
596 /* Does the target supports the load directly? */
597 icode = direct_optab_handler (atomic_load_optab, mode);
598 if (icode != CODE_FOR_nothing)
599 return true;
601 /* If the size of the object is greater than word size on this target,
602 then we assume that a load will not be atomic. Also see
603 expand_atomic_load. */
604 return GET_MODE_PRECISION (mode) <= BITS_PER_WORD;
607 /* Determine whether "1 << x" is relatively cheap in word_mode. */
609 bool
610 lshift_cheap_p (bool speed_p)
612 /* FIXME: This should be made target dependent via this "this_target"
613 mechanism, similar to e.g. can_copy_init_p in gcse.c. */
614 static bool init[2] = { false, false };
615 static bool cheap[2] = { true, true };
617 /* If the targer has no lshift in word_mode, the operation will most
618 probably not be cheap. ??? Does GCC even work for such targets? */
619 if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
620 return false;
622 if (!init[speed_p])
624 rtx reg = gen_raw_REG (word_mode, 10000);
625 int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
626 word_mode, speed_p);
627 cheap[speed_p] = cost < COSTS_N_INSNS (3);
628 init[speed_p] = true;
631 return cheap[speed_p];