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