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