1*38fd1498Szrj /* IR-agnostic target query functions relating to optabs
2*38fd1498Szrj Copyright (C) 1987-2018 Free Software Foundation, Inc.
3*38fd1498Szrj
4*38fd1498Szrj This file is part of GCC.
5*38fd1498Szrj
6*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
7*38fd1498Szrj the terms of the GNU General Public License as published by the Free
8*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
9*38fd1498Szrj version.
10*38fd1498Szrj
11*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
13*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14*38fd1498Szrj for more details.
15*38fd1498Szrj
16*38fd1498Szrj You should have received a copy of the GNU General Public License
17*38fd1498Szrj along with GCC; see the file COPYING3. If not see
18*38fd1498Szrj <http://www.gnu.org/licenses/>. */
19*38fd1498Szrj
20*38fd1498Szrj
21*38fd1498Szrj #include "config.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj #include "coretypes.h"
24*38fd1498Szrj #include "target.h"
25*38fd1498Szrj #include "insn-codes.h"
26*38fd1498Szrj #include "optabs-query.h"
27*38fd1498Szrj #include "optabs-libfuncs.h"
28*38fd1498Szrj #include "insn-config.h"
29*38fd1498Szrj #include "rtl.h"
30*38fd1498Szrj #include "recog.h"
31*38fd1498Szrj #include "vec-perm-indices.h"
32*38fd1498Szrj
33*38fd1498Szrj struct target_optabs default_target_optabs;
34*38fd1498Szrj struct target_optabs *this_fn_optabs = &default_target_optabs;
35*38fd1498Szrj #if SWITCHABLE_TARGET
36*38fd1498Szrj struct target_optabs *this_target_optabs = &default_target_optabs;
37*38fd1498Szrj #endif
38*38fd1498Szrj
39*38fd1498Szrj /* Return the insn used to perform conversion OP from mode FROM_MODE
40*38fd1498Szrj to mode TO_MODE; return CODE_FOR_nothing if the target does not have
41*38fd1498Szrj such an insn, or if it is unsuitable for optimization type OPT_TYPE. */
42*38fd1498Szrj
43*38fd1498Szrj insn_code
convert_optab_handler(convert_optab optab,machine_mode to_mode,machine_mode from_mode,optimization_type opt_type)44*38fd1498Szrj convert_optab_handler (convert_optab optab, machine_mode to_mode,
45*38fd1498Szrj machine_mode from_mode, optimization_type opt_type)
46*38fd1498Szrj {
47*38fd1498Szrj insn_code icode = convert_optab_handler (optab, to_mode, from_mode);
48*38fd1498Szrj if (icode == CODE_FOR_nothing
49*38fd1498Szrj || !targetm.optab_supported_p (optab, to_mode, from_mode, opt_type))
50*38fd1498Szrj return CODE_FOR_nothing;
51*38fd1498Szrj return icode;
52*38fd1498Szrj }
53*38fd1498Szrj
54*38fd1498Szrj /* Return the insn used to implement mode MODE of OP; return
55*38fd1498Szrj CODE_FOR_nothing if the target does not have such an insn,
56*38fd1498Szrj or if it is unsuitable for optimization type OPT_TYPE. */
57*38fd1498Szrj
58*38fd1498Szrj insn_code
direct_optab_handler(convert_optab optab,machine_mode mode,optimization_type opt_type)59*38fd1498Szrj direct_optab_handler (convert_optab optab, machine_mode mode,
60*38fd1498Szrj optimization_type opt_type)
61*38fd1498Szrj {
62*38fd1498Szrj insn_code icode = direct_optab_handler (optab, mode);
63*38fd1498Szrj if (icode == CODE_FOR_nothing
64*38fd1498Szrj || !targetm.optab_supported_p (optab, mode, mode, opt_type))
65*38fd1498Szrj return CODE_FOR_nothing;
66*38fd1498Szrj return icode;
67*38fd1498Szrj }
68*38fd1498Szrj
69*38fd1498Szrj /* Enumerates the possible types of structure operand to an
70*38fd1498Szrj extraction_insn. */
71*38fd1498Szrj enum extraction_type { ET_unaligned_mem, ET_reg };
72*38fd1498Szrj
73*38fd1498Szrj /* Check whether insv, extv or extzv pattern ICODE can be used for an
74*38fd1498Szrj insertion or extraction of type TYPE on a structure of mode MODE.
75*38fd1498Szrj Return true if so and fill in *INSN accordingly. STRUCT_OP is the
76*38fd1498Szrj operand number of the structure (the first sign_extract or zero_extract
77*38fd1498Szrj operand) and FIELD_OP is the operand number of the field (the other
78*38fd1498Szrj side of the set from the sign_extract or zero_extract). */
79*38fd1498Szrj
80*38fd1498Szrj static bool
get_traditional_extraction_insn(extraction_insn * insn,enum extraction_type type,machine_mode mode,enum insn_code icode,int struct_op,int field_op)81*38fd1498Szrj get_traditional_extraction_insn (extraction_insn *insn,
82*38fd1498Szrj enum extraction_type type,
83*38fd1498Szrj machine_mode mode,
84*38fd1498Szrj enum insn_code icode,
85*38fd1498Szrj int struct_op, int field_op)
86*38fd1498Szrj {
87*38fd1498Szrj const struct insn_data_d *data = &insn_data[icode];
88*38fd1498Szrj
89*38fd1498Szrj machine_mode struct_mode = data->operand[struct_op].mode;
90*38fd1498Szrj if (struct_mode == VOIDmode)
91*38fd1498Szrj struct_mode = word_mode;
92*38fd1498Szrj if (mode != struct_mode)
93*38fd1498Szrj return false;
94*38fd1498Szrj
95*38fd1498Szrj machine_mode field_mode = data->operand[field_op].mode;
96*38fd1498Szrj if (field_mode == VOIDmode)
97*38fd1498Szrj field_mode = word_mode;
98*38fd1498Szrj
99*38fd1498Szrj machine_mode pos_mode = data->operand[struct_op + 2].mode;
100*38fd1498Szrj if (pos_mode == VOIDmode)
101*38fd1498Szrj pos_mode = word_mode;
102*38fd1498Szrj
103*38fd1498Szrj insn->icode = icode;
104*38fd1498Szrj insn->field_mode = as_a <scalar_int_mode> (field_mode);
105*38fd1498Szrj if (type == ET_unaligned_mem)
106*38fd1498Szrj insn->struct_mode = byte_mode;
107*38fd1498Szrj else if (struct_mode == BLKmode)
108*38fd1498Szrj insn->struct_mode = opt_scalar_int_mode ();
109*38fd1498Szrj else
110*38fd1498Szrj insn->struct_mode = as_a <scalar_int_mode> (struct_mode);
111*38fd1498Szrj insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
112*38fd1498Szrj return true;
113*38fd1498Szrj }
114*38fd1498Szrj
115*38fd1498Szrj /* Return true if an optab exists to perform an insertion or extraction
116*38fd1498Szrj of type TYPE in mode MODE. Describe the instruction in *INSN if so.
117*38fd1498Szrj
118*38fd1498Szrj REG_OPTAB is the optab to use for register structures and
119*38fd1498Szrj MISALIGN_OPTAB is the optab to use for misaligned memory structures.
120*38fd1498Szrj POS_OP is the operand number of the bit position. */
121*38fd1498Szrj
122*38fd1498Szrj static bool
get_optab_extraction_insn(struct extraction_insn * insn,enum extraction_type type,machine_mode mode,direct_optab reg_optab,direct_optab misalign_optab,int pos_op)123*38fd1498Szrj get_optab_extraction_insn (struct extraction_insn *insn,
124*38fd1498Szrj enum extraction_type type,
125*38fd1498Szrj machine_mode mode, direct_optab reg_optab,
126*38fd1498Szrj direct_optab misalign_optab, int pos_op)
127*38fd1498Szrj {
128*38fd1498Szrj direct_optab optab = (type == ET_unaligned_mem ? misalign_optab : reg_optab);
129*38fd1498Szrj enum insn_code icode = direct_optab_handler (optab, mode);
130*38fd1498Szrj if (icode == CODE_FOR_nothing)
131*38fd1498Szrj return false;
132*38fd1498Szrj
133*38fd1498Szrj const struct insn_data_d *data = &insn_data[icode];
134*38fd1498Szrj
135*38fd1498Szrj machine_mode pos_mode = data->operand[pos_op].mode;
136*38fd1498Szrj if (pos_mode == VOIDmode)
137*38fd1498Szrj pos_mode = word_mode;
138*38fd1498Szrj
139*38fd1498Szrj insn->icode = icode;
140*38fd1498Szrj insn->field_mode = as_a <scalar_int_mode> (mode);
141*38fd1498Szrj if (type == ET_unaligned_mem)
142*38fd1498Szrj insn->struct_mode = opt_scalar_int_mode ();
143*38fd1498Szrj else
144*38fd1498Szrj insn->struct_mode = insn->field_mode;
145*38fd1498Szrj insn->pos_mode = as_a <scalar_int_mode> (pos_mode);
146*38fd1498Szrj return true;
147*38fd1498Szrj }
148*38fd1498Szrj
149*38fd1498Szrj /* Return true if an instruction exists to perform an insertion or
150*38fd1498Szrj extraction (PATTERN says which) of type TYPE in mode MODE.
151*38fd1498Szrj Describe the instruction in *INSN if so. */
152*38fd1498Szrj
153*38fd1498Szrj static bool
get_extraction_insn(extraction_insn * insn,enum extraction_pattern pattern,enum extraction_type type,machine_mode mode)154*38fd1498Szrj get_extraction_insn (extraction_insn *insn,
155*38fd1498Szrj enum extraction_pattern pattern,
156*38fd1498Szrj enum extraction_type type,
157*38fd1498Szrj machine_mode mode)
158*38fd1498Szrj {
159*38fd1498Szrj switch (pattern)
160*38fd1498Szrj {
161*38fd1498Szrj case EP_insv:
162*38fd1498Szrj if (targetm.have_insv ()
163*38fd1498Szrj && get_traditional_extraction_insn (insn, type, mode,
164*38fd1498Szrj targetm.code_for_insv, 0, 3))
165*38fd1498Szrj return true;
166*38fd1498Szrj return get_optab_extraction_insn (insn, type, mode, insv_optab,
167*38fd1498Szrj insvmisalign_optab, 2);
168*38fd1498Szrj
169*38fd1498Szrj case EP_extv:
170*38fd1498Szrj if (targetm.have_extv ()
171*38fd1498Szrj && get_traditional_extraction_insn (insn, type, mode,
172*38fd1498Szrj targetm.code_for_extv, 1, 0))
173*38fd1498Szrj return true;
174*38fd1498Szrj return get_optab_extraction_insn (insn, type, mode, extv_optab,
175*38fd1498Szrj extvmisalign_optab, 3);
176*38fd1498Szrj
177*38fd1498Szrj case EP_extzv:
178*38fd1498Szrj if (targetm.have_extzv ()
179*38fd1498Szrj && get_traditional_extraction_insn (insn, type, mode,
180*38fd1498Szrj targetm.code_for_extzv, 1, 0))
181*38fd1498Szrj return true;
182*38fd1498Szrj return get_optab_extraction_insn (insn, type, mode, extzv_optab,
183*38fd1498Szrj extzvmisalign_optab, 3);
184*38fd1498Szrj
185*38fd1498Szrj default:
186*38fd1498Szrj gcc_unreachable ();
187*38fd1498Szrj }
188*38fd1498Szrj }
189*38fd1498Szrj
190*38fd1498Szrj /* Return true if an instruction exists to access a field of mode
191*38fd1498Szrj FIELDMODE in a structure that has STRUCT_BITS significant bits.
192*38fd1498Szrj Describe the "best" such instruction in *INSN if so. PATTERN and
193*38fd1498Szrj TYPE describe the type of insertion or extraction we want to perform.
194*38fd1498Szrj
195*38fd1498Szrj For an insertion, the number of significant structure bits includes
196*38fd1498Szrj all bits of the target. For an extraction, it need only include the
197*38fd1498Szrj most significant bit of the field. Larger widths are acceptable
198*38fd1498Szrj in both cases. */
199*38fd1498Szrj
200*38fd1498Szrj static bool
get_best_extraction_insn(extraction_insn * insn,enum extraction_pattern pattern,enum extraction_type type,unsigned HOST_WIDE_INT struct_bits,machine_mode field_mode)201*38fd1498Szrj get_best_extraction_insn (extraction_insn *insn,
202*38fd1498Szrj enum extraction_pattern pattern,
203*38fd1498Szrj enum extraction_type type,
204*38fd1498Szrj unsigned HOST_WIDE_INT struct_bits,
205*38fd1498Szrj machine_mode field_mode)
206*38fd1498Szrj {
207*38fd1498Szrj opt_scalar_int_mode mode_iter;
208*38fd1498Szrj FOR_EACH_MODE_FROM (mode_iter, smallest_int_mode_for_size (struct_bits))
209*38fd1498Szrj {
210*38fd1498Szrj scalar_int_mode mode = mode_iter.require ();
211*38fd1498Szrj if (get_extraction_insn (insn, pattern, type, mode))
212*38fd1498Szrj {
213*38fd1498Szrj FOR_EACH_MODE_FROM (mode_iter, mode)
214*38fd1498Szrj {
215*38fd1498Szrj mode = mode_iter.require ();
216*38fd1498Szrj if (maybe_gt (GET_MODE_SIZE (mode), GET_MODE_SIZE (field_mode))
217*38fd1498Szrj || TRULY_NOOP_TRUNCATION_MODES_P (insn->field_mode,
218*38fd1498Szrj field_mode))
219*38fd1498Szrj break;
220*38fd1498Szrj get_extraction_insn (insn, pattern, type, mode);
221*38fd1498Szrj }
222*38fd1498Szrj return true;
223*38fd1498Szrj }
224*38fd1498Szrj }
225*38fd1498Szrj return false;
226*38fd1498Szrj }
227*38fd1498Szrj
228*38fd1498Szrj /* Return true if an instruction exists to access a field of mode
229*38fd1498Szrj FIELDMODE in a register structure that has STRUCT_BITS significant bits.
230*38fd1498Szrj Describe the "best" such instruction in *INSN if so. PATTERN describes
231*38fd1498Szrj the type of insertion or extraction we want to perform.
232*38fd1498Szrj
233*38fd1498Szrj For an insertion, the number of significant structure bits includes
234*38fd1498Szrj all bits of the target. For an extraction, it need only include the
235*38fd1498Szrj most significant bit of the field. Larger widths are acceptable
236*38fd1498Szrj in both cases. */
237*38fd1498Szrj
238*38fd1498Szrj bool
get_best_reg_extraction_insn(extraction_insn * insn,enum extraction_pattern pattern,unsigned HOST_WIDE_INT struct_bits,machine_mode field_mode)239*38fd1498Szrj get_best_reg_extraction_insn (extraction_insn *insn,
240*38fd1498Szrj enum extraction_pattern pattern,
241*38fd1498Szrj unsigned HOST_WIDE_INT struct_bits,
242*38fd1498Szrj machine_mode field_mode)
243*38fd1498Szrj {
244*38fd1498Szrj return get_best_extraction_insn (insn, pattern, ET_reg, struct_bits,
245*38fd1498Szrj field_mode);
246*38fd1498Szrj }
247*38fd1498Szrj
248*38fd1498Szrj /* Return true if an instruction exists to access a field of BITSIZE
249*38fd1498Szrj bits starting BITNUM bits into a memory structure. Describe the
250*38fd1498Szrj "best" such instruction in *INSN if so. PATTERN describes the type
251*38fd1498Szrj of insertion or extraction we want to perform and FIELDMODE is the
252*38fd1498Szrj natural mode of the extracted field.
253*38fd1498Szrj
254*38fd1498Szrj The instructions considered here only access bytes that overlap
255*38fd1498Szrj the bitfield; they do not touch any surrounding bytes. */
256*38fd1498Szrj
257*38fd1498Szrj bool
get_best_mem_extraction_insn(extraction_insn * insn,enum extraction_pattern pattern,HOST_WIDE_INT bitsize,HOST_WIDE_INT bitnum,machine_mode field_mode)258*38fd1498Szrj get_best_mem_extraction_insn (extraction_insn *insn,
259*38fd1498Szrj enum extraction_pattern pattern,
260*38fd1498Szrj HOST_WIDE_INT bitsize, HOST_WIDE_INT bitnum,
261*38fd1498Szrj machine_mode field_mode)
262*38fd1498Szrj {
263*38fd1498Szrj unsigned HOST_WIDE_INT struct_bits = (bitnum % BITS_PER_UNIT
264*38fd1498Szrj + bitsize
265*38fd1498Szrj + BITS_PER_UNIT - 1);
266*38fd1498Szrj struct_bits -= struct_bits % BITS_PER_UNIT;
267*38fd1498Szrj return get_best_extraction_insn (insn, pattern, ET_unaligned_mem,
268*38fd1498Szrj struct_bits, field_mode);
269*38fd1498Szrj }
270*38fd1498Szrj
271*38fd1498Szrj /* Return the insn code used to extend FROM_MODE to TO_MODE.
272*38fd1498Szrj UNSIGNEDP specifies zero-extension instead of sign-extension. If
273*38fd1498Szrj no such operation exists, CODE_FOR_nothing will be returned. */
274*38fd1498Szrj
275*38fd1498Szrj enum insn_code
can_extend_p(machine_mode to_mode,machine_mode from_mode,int unsignedp)276*38fd1498Szrj can_extend_p (machine_mode to_mode, machine_mode from_mode,
277*38fd1498Szrj int unsignedp)
278*38fd1498Szrj {
279*38fd1498Szrj if (unsignedp < 0 && targetm.have_ptr_extend ())
280*38fd1498Szrj return targetm.code_for_ptr_extend;
281*38fd1498Szrj
282*38fd1498Szrj convert_optab tab = unsignedp ? zext_optab : sext_optab;
283*38fd1498Szrj return convert_optab_handler (tab, to_mode, from_mode);
284*38fd1498Szrj }
285*38fd1498Szrj
286*38fd1498Szrj /* Return the insn code to convert fixed-point mode FIXMODE to floating-point
287*38fd1498Szrj mode FLTMODE, or CODE_FOR_nothing if no such instruction exists.
288*38fd1498Szrj UNSIGNEDP specifies whether FIXMODE is unsigned. */
289*38fd1498Szrj
290*38fd1498Szrj enum insn_code
can_float_p(machine_mode fltmode,machine_mode fixmode,int unsignedp)291*38fd1498Szrj can_float_p (machine_mode fltmode, machine_mode fixmode,
292*38fd1498Szrj int unsignedp)
293*38fd1498Szrj {
294*38fd1498Szrj convert_optab tab = unsignedp ? ufloat_optab : sfloat_optab;
295*38fd1498Szrj return convert_optab_handler (tab, fltmode, fixmode);
296*38fd1498Szrj }
297*38fd1498Szrj
298*38fd1498Szrj /* Return the insn code to convert floating-point mode FLTMODE to fixed-point
299*38fd1498Szrj mode FIXMODE, or CODE_FOR_nothing if no such instruction exists.
300*38fd1498Szrj UNSIGNEDP specifies whether FIXMODE is unsigned.
301*38fd1498Szrj
302*38fd1498Szrj On a successful return, set *TRUNCP_PTR to true if it is necessary to
303*38fd1498Szrj output an explicit FTRUNC before the instruction. */
304*38fd1498Szrj
305*38fd1498Szrj enum insn_code
can_fix_p(machine_mode fixmode,machine_mode fltmode,int unsignedp,bool * truncp_ptr)306*38fd1498Szrj can_fix_p (machine_mode fixmode, machine_mode fltmode,
307*38fd1498Szrj int unsignedp, bool *truncp_ptr)
308*38fd1498Szrj {
309*38fd1498Szrj convert_optab tab;
310*38fd1498Szrj enum insn_code icode;
311*38fd1498Szrj
312*38fd1498Szrj tab = unsignedp ? ufixtrunc_optab : sfixtrunc_optab;
313*38fd1498Szrj icode = convert_optab_handler (tab, fixmode, fltmode);
314*38fd1498Szrj if (icode != CODE_FOR_nothing)
315*38fd1498Szrj {
316*38fd1498Szrj *truncp_ptr = false;
317*38fd1498Szrj return icode;
318*38fd1498Szrj }
319*38fd1498Szrj
320*38fd1498Szrj /* FIXME: This requires a port to define both FIX and FTRUNC pattern
321*38fd1498Szrj for this to work. We need to rework the fix* and ftrunc* patterns
322*38fd1498Szrj and documentation. */
323*38fd1498Szrj tab = unsignedp ? ufix_optab : sfix_optab;
324*38fd1498Szrj icode = convert_optab_handler (tab, fixmode, fltmode);
325*38fd1498Szrj if (icode != CODE_FOR_nothing
326*38fd1498Szrj && optab_handler (ftrunc_optab, fltmode) != CODE_FOR_nothing)
327*38fd1498Szrj {
328*38fd1498Szrj *truncp_ptr = true;
329*38fd1498Szrj return icode;
330*38fd1498Szrj }
331*38fd1498Szrj
332*38fd1498Szrj return CODE_FOR_nothing;
333*38fd1498Szrj }
334*38fd1498Szrj
335*38fd1498Szrj /* Return nonzero if a conditional move of mode MODE is supported.
336*38fd1498Szrj
337*38fd1498Szrj This function is for combine so it can tell whether an insn that looks
338*38fd1498Szrj like a conditional move is actually supported by the hardware. If we
339*38fd1498Szrj guess wrong we lose a bit on optimization, but that's it. */
340*38fd1498Szrj /* ??? sparc64 supports conditionally moving integers values based on fp
341*38fd1498Szrj comparisons, and vice versa. How do we handle them? */
342*38fd1498Szrj
343*38fd1498Szrj bool
can_conditionally_move_p(machine_mode mode)344*38fd1498Szrj can_conditionally_move_p (machine_mode mode)
345*38fd1498Szrj {
346*38fd1498Szrj return direct_optab_handler (movcc_optab, mode) != CODE_FOR_nothing;
347*38fd1498Szrj }
348*38fd1498Szrj
349*38fd1498Szrj /* If a target doesn't implement a permute on a vector with multibyte
350*38fd1498Szrj elements, we can try to do the same permute on byte elements.
351*38fd1498Szrj If this makes sense for vector mode MODE then return the appropriate
352*38fd1498Szrj byte vector mode. */
353*38fd1498Szrj
354*38fd1498Szrj opt_machine_mode
qimode_for_vec_perm(machine_mode mode)355*38fd1498Szrj qimode_for_vec_perm (machine_mode mode)
356*38fd1498Szrj {
357*38fd1498Szrj machine_mode qimode;
358*38fd1498Szrj if (GET_MODE_INNER (mode) != QImode
359*38fd1498Szrj && mode_for_vector (QImode, GET_MODE_SIZE (mode)).exists (&qimode)
360*38fd1498Szrj && VECTOR_MODE_P (qimode))
361*38fd1498Szrj return qimode;
362*38fd1498Szrj return opt_machine_mode ();
363*38fd1498Szrj }
364*38fd1498Szrj
365*38fd1498Szrj /* Return true if selector SEL can be represented in the integer
366*38fd1498Szrj equivalent of vector mode MODE. */
367*38fd1498Szrj
368*38fd1498Szrj bool
selector_fits_mode_p(machine_mode mode,const vec_perm_indices & sel)369*38fd1498Szrj selector_fits_mode_p (machine_mode mode, const vec_perm_indices &sel)
370*38fd1498Szrj {
371*38fd1498Szrj unsigned HOST_WIDE_INT mask = GET_MODE_MASK (GET_MODE_INNER (mode));
372*38fd1498Szrj return (mask == HOST_WIDE_INT_M1U
373*38fd1498Szrj || sel.all_in_range_p (0, mask + 1));
374*38fd1498Szrj }
375*38fd1498Szrj
376*38fd1498Szrj /* Return true if VEC_PERM_EXPRs with variable selector operands can be
377*38fd1498Szrj expanded using SIMD extensions of the CPU. MODE is the mode of the
378*38fd1498Szrj vectors being permuted. */
379*38fd1498Szrj
380*38fd1498Szrj bool
can_vec_perm_var_p(machine_mode mode)381*38fd1498Szrj can_vec_perm_var_p (machine_mode mode)
382*38fd1498Szrj {
383*38fd1498Szrj /* If the target doesn't implement a vector mode for the vector type,
384*38fd1498Szrj then no operations are supported. */
385*38fd1498Szrj if (!VECTOR_MODE_P (mode))
386*38fd1498Szrj return false;
387*38fd1498Szrj
388*38fd1498Szrj if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
389*38fd1498Szrj return true;
390*38fd1498Szrj
391*38fd1498Szrj /* We allow fallback to a QI vector mode, and adjust the mask. */
392*38fd1498Szrj machine_mode qimode;
393*38fd1498Szrj if (!qimode_for_vec_perm (mode).exists (&qimode)
394*38fd1498Szrj || maybe_gt (GET_MODE_NUNITS (qimode), GET_MODE_MASK (QImode) + 1))
395*38fd1498Szrj return false;
396*38fd1498Szrj
397*38fd1498Szrj if (direct_optab_handler (vec_perm_optab, qimode) == CODE_FOR_nothing)
398*38fd1498Szrj return false;
399*38fd1498Szrj
400*38fd1498Szrj /* In order to support the lowering of variable permutations,
401*38fd1498Szrj we need to support shifts and adds. */
402*38fd1498Szrj if (GET_MODE_UNIT_SIZE (mode) > 2
403*38fd1498Szrj && optab_handler (ashl_optab, mode) == CODE_FOR_nothing
404*38fd1498Szrj && optab_handler (vashl_optab, mode) == CODE_FOR_nothing)
405*38fd1498Szrj return false;
406*38fd1498Szrj if (optab_handler (add_optab, qimode) == CODE_FOR_nothing)
407*38fd1498Szrj return false;
408*38fd1498Szrj
409*38fd1498Szrj return true;
410*38fd1498Szrj }
411*38fd1498Szrj
412*38fd1498Szrj /* Return true if the target directly supports VEC_PERM_EXPRs on vectors
413*38fd1498Szrj of mode MODE using the selector SEL. ALLOW_VARIABLE_P is true if it
414*38fd1498Szrj is acceptable to force the selector into a register and use a variable
415*38fd1498Szrj permute (if the target supports that).
416*38fd1498Szrj
417*38fd1498Szrj Note that additional permutations representing whole-vector shifts may
418*38fd1498Szrj also be handled via the vec_shr optab, but only where the second input
419*38fd1498Szrj vector is entirely constant zeroes; this case is not dealt with here. */
420*38fd1498Szrj
421*38fd1498Szrj bool
can_vec_perm_const_p(machine_mode mode,const vec_perm_indices & sel,bool allow_variable_p)422*38fd1498Szrj can_vec_perm_const_p (machine_mode mode, const vec_perm_indices &sel,
423*38fd1498Szrj bool allow_variable_p)
424*38fd1498Szrj {
425*38fd1498Szrj /* If the target doesn't implement a vector mode for the vector type,
426*38fd1498Szrj then no operations are supported. */
427*38fd1498Szrj if (!VECTOR_MODE_P (mode))
428*38fd1498Szrj return false;
429*38fd1498Szrj
430*38fd1498Szrj /* It's probably cheaper to test for the variable case first. */
431*38fd1498Szrj if (allow_variable_p && selector_fits_mode_p (mode, sel))
432*38fd1498Szrj {
433*38fd1498Szrj if (direct_optab_handler (vec_perm_optab, mode) != CODE_FOR_nothing)
434*38fd1498Szrj return true;
435*38fd1498Szrj
436*38fd1498Szrj /* Unlike can_vec_perm_var_p, we don't need to test for optabs
437*38fd1498Szrj related computing the QImode selector, since that happens at
438*38fd1498Szrj compile time. */
439*38fd1498Szrj machine_mode qimode;
440*38fd1498Szrj if (qimode_for_vec_perm (mode).exists (&qimode))
441*38fd1498Szrj {
442*38fd1498Szrj vec_perm_indices qimode_indices;
443*38fd1498Szrj qimode_indices.new_expanded_vector (sel, GET_MODE_UNIT_SIZE (mode));
444*38fd1498Szrj if (selector_fits_mode_p (qimode, qimode_indices)
445*38fd1498Szrj && (direct_optab_handler (vec_perm_optab, qimode)
446*38fd1498Szrj != CODE_FOR_nothing))
447*38fd1498Szrj return true;
448*38fd1498Szrj }
449*38fd1498Szrj }
450*38fd1498Szrj
451*38fd1498Szrj if (targetm.vectorize.vec_perm_const != NULL)
452*38fd1498Szrj {
453*38fd1498Szrj if (targetm.vectorize.vec_perm_const (mode, NULL_RTX, NULL_RTX,
454*38fd1498Szrj NULL_RTX, sel))
455*38fd1498Szrj return true;
456*38fd1498Szrj
457*38fd1498Szrj /* ??? For completeness, we ought to check the QImode version of
458*38fd1498Szrj vec_perm_const_optab. But all users of this implicit lowering
459*38fd1498Szrj feature implement the variable vec_perm_optab, and the ia64
460*38fd1498Szrj port specifically doesn't want us to lower V2SF operations
461*38fd1498Szrj into integer operations. */
462*38fd1498Szrj }
463*38fd1498Szrj
464*38fd1498Szrj return false;
465*38fd1498Szrj }
466*38fd1498Szrj
467*38fd1498Szrj /* Find a widening optab even if it doesn't widen as much as we want.
468*38fd1498Szrj E.g. if from_mode is HImode, and to_mode is DImode, and there is no
469*38fd1498Szrj direct HI->SI insn, then return SI->DI, if that exists. */
470*38fd1498Szrj
471*38fd1498Szrj enum insn_code
find_widening_optab_handler_and_mode(optab op,machine_mode to_mode,machine_mode from_mode,machine_mode * found_mode)472*38fd1498Szrj find_widening_optab_handler_and_mode (optab op, machine_mode to_mode,
473*38fd1498Szrj machine_mode from_mode,
474*38fd1498Szrj machine_mode *found_mode)
475*38fd1498Szrj {
476*38fd1498Szrj machine_mode limit_mode = to_mode;
477*38fd1498Szrj if (is_a <scalar_int_mode> (from_mode))
478*38fd1498Szrj {
479*38fd1498Szrj gcc_checking_assert (is_a <scalar_int_mode> (to_mode)
480*38fd1498Szrj && known_lt (GET_MODE_PRECISION (from_mode),
481*38fd1498Szrj GET_MODE_PRECISION (to_mode)));
482*38fd1498Szrj /* The modes after FROM_MODE are all MODE_INT, so the only
483*38fd1498Szrj MODE_PARTIAL_INT mode we consider is FROM_MODE itself.
484*38fd1498Szrj If LIMIT_MODE is MODE_PARTIAL_INT, stop at the containing
485*38fd1498Szrj MODE_INT. */
486*38fd1498Szrj if (GET_MODE_CLASS (limit_mode) == MODE_PARTIAL_INT)
487*38fd1498Szrj limit_mode = GET_MODE_WIDER_MODE (limit_mode).require ();
488*38fd1498Szrj }
489*38fd1498Szrj else
490*38fd1498Szrj gcc_checking_assert (GET_MODE_CLASS (from_mode) == GET_MODE_CLASS (to_mode)
491*38fd1498Szrj && from_mode < to_mode);
492*38fd1498Szrj FOR_EACH_MODE (from_mode, from_mode, limit_mode)
493*38fd1498Szrj {
494*38fd1498Szrj enum insn_code handler = convert_optab_handler (op, to_mode, from_mode);
495*38fd1498Szrj
496*38fd1498Szrj if (handler != CODE_FOR_nothing)
497*38fd1498Szrj {
498*38fd1498Szrj if (found_mode)
499*38fd1498Szrj *found_mode = from_mode;
500*38fd1498Szrj return handler;
501*38fd1498Szrj }
502*38fd1498Szrj }
503*38fd1498Szrj
504*38fd1498Szrj return CODE_FOR_nothing;
505*38fd1498Szrj }
506*38fd1498Szrj
507*38fd1498Szrj /* Return non-zero if a highpart multiply is supported of can be synthisized.
508*38fd1498Szrj For the benefit of expand_mult_highpart, the return value is 1 for direct,
509*38fd1498Szrj 2 for even/odd widening, and 3 for hi/lo widening. */
510*38fd1498Szrj
511*38fd1498Szrj int
can_mult_highpart_p(machine_mode mode,bool uns_p)512*38fd1498Szrj can_mult_highpart_p (machine_mode mode, bool uns_p)
513*38fd1498Szrj {
514*38fd1498Szrj optab op;
515*38fd1498Szrj
516*38fd1498Szrj op = uns_p ? umul_highpart_optab : smul_highpart_optab;
517*38fd1498Szrj if (optab_handler (op, mode) != CODE_FOR_nothing)
518*38fd1498Szrj return 1;
519*38fd1498Szrj
520*38fd1498Szrj /* If the mode is an integral vector, synth from widening operations. */
521*38fd1498Szrj if (GET_MODE_CLASS (mode) != MODE_VECTOR_INT)
522*38fd1498Szrj return 0;
523*38fd1498Szrj
524*38fd1498Szrj poly_int64 nunits = GET_MODE_NUNITS (mode);
525*38fd1498Szrj
526*38fd1498Szrj op = uns_p ? vec_widen_umult_even_optab : vec_widen_smult_even_optab;
527*38fd1498Szrj if (optab_handler (op, mode) != CODE_FOR_nothing)
528*38fd1498Szrj {
529*38fd1498Szrj op = uns_p ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab;
530*38fd1498Szrj if (optab_handler (op, mode) != CODE_FOR_nothing)
531*38fd1498Szrj {
532*38fd1498Szrj /* The encoding has 2 interleaved stepped patterns. */
533*38fd1498Szrj vec_perm_builder sel (nunits, 2, 3);
534*38fd1498Szrj for (unsigned int i = 0; i < 6; ++i)
535*38fd1498Szrj sel.quick_push (!BYTES_BIG_ENDIAN
536*38fd1498Szrj + (i & ~1)
537*38fd1498Szrj + ((i & 1) ? nunits : 0));
538*38fd1498Szrj vec_perm_indices indices (sel, 2, nunits);
539*38fd1498Szrj if (can_vec_perm_const_p (mode, indices))
540*38fd1498Szrj return 2;
541*38fd1498Szrj }
542*38fd1498Szrj }
543*38fd1498Szrj
544*38fd1498Szrj op = uns_p ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab;
545*38fd1498Szrj if (optab_handler (op, mode) != CODE_FOR_nothing)
546*38fd1498Szrj {
547*38fd1498Szrj op = uns_p ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab;
548*38fd1498Szrj if (optab_handler (op, mode) != CODE_FOR_nothing)
549*38fd1498Szrj {
550*38fd1498Szrj /* The encoding has a single stepped pattern. */
551*38fd1498Szrj vec_perm_builder sel (nunits, 1, 3);
552*38fd1498Szrj for (unsigned int i = 0; i < 3; ++i)
553*38fd1498Szrj sel.quick_push (2 * i + (BYTES_BIG_ENDIAN ? 0 : 1));
554*38fd1498Szrj vec_perm_indices indices (sel, 2, nunits);
555*38fd1498Szrj if (can_vec_perm_const_p (mode, indices))
556*38fd1498Szrj return 3;
557*38fd1498Szrj }
558*38fd1498Szrj }
559*38fd1498Szrj
560*38fd1498Szrj return 0;
561*38fd1498Szrj }
562*38fd1498Szrj
563*38fd1498Szrj /* Return true if target supports vector masked load/store for mode. */
564*38fd1498Szrj
565*38fd1498Szrj bool
can_vec_mask_load_store_p(machine_mode mode,machine_mode mask_mode,bool is_load)566*38fd1498Szrj can_vec_mask_load_store_p (machine_mode mode,
567*38fd1498Szrj machine_mode mask_mode,
568*38fd1498Szrj bool is_load)
569*38fd1498Szrj {
570*38fd1498Szrj optab op = is_load ? maskload_optab : maskstore_optab;
571*38fd1498Szrj machine_mode vmode;
572*38fd1498Szrj
573*38fd1498Szrj /* If mode is vector mode, check it directly. */
574*38fd1498Szrj if (VECTOR_MODE_P (mode))
575*38fd1498Szrj return convert_optab_handler (op, mode, mask_mode) != CODE_FOR_nothing;
576*38fd1498Szrj
577*38fd1498Szrj /* Otherwise, return true if there is some vector mode with
578*38fd1498Szrj the mask load/store supported. */
579*38fd1498Szrj
580*38fd1498Szrj /* See if there is any chance the mask load or store might be
581*38fd1498Szrj vectorized. If not, punt. */
582*38fd1498Szrj scalar_mode smode;
583*38fd1498Szrj if (!is_a <scalar_mode> (mode, &smode))
584*38fd1498Szrj return false;
585*38fd1498Szrj
586*38fd1498Szrj vmode = targetm.vectorize.preferred_simd_mode (smode);
587*38fd1498Szrj if (!VECTOR_MODE_P (vmode))
588*38fd1498Szrj return false;
589*38fd1498Szrj
590*38fd1498Szrj if ((targetm.vectorize.get_mask_mode
591*38fd1498Szrj (GET_MODE_NUNITS (vmode), GET_MODE_SIZE (vmode)).exists (&mask_mode))
592*38fd1498Szrj && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
593*38fd1498Szrj return true;
594*38fd1498Szrj
595*38fd1498Szrj auto_vector_sizes vector_sizes;
596*38fd1498Szrj targetm.vectorize.autovectorize_vector_sizes (&vector_sizes);
597*38fd1498Szrj for (unsigned int i = 0; i < vector_sizes.length (); ++i)
598*38fd1498Szrj {
599*38fd1498Szrj poly_uint64 cur = vector_sizes[i];
600*38fd1498Szrj poly_uint64 nunits;
601*38fd1498Szrj if (!multiple_p (cur, GET_MODE_SIZE (smode), &nunits))
602*38fd1498Szrj continue;
603*38fd1498Szrj if (mode_for_vector (smode, nunits).exists (&vmode)
604*38fd1498Szrj && VECTOR_MODE_P (vmode)
605*38fd1498Szrj && targetm.vectorize.get_mask_mode (nunits, cur).exists (&mask_mode)
606*38fd1498Szrj && convert_optab_handler (op, vmode, mask_mode) != CODE_FOR_nothing)
607*38fd1498Szrj return true;
608*38fd1498Szrj }
609*38fd1498Szrj return false;
610*38fd1498Szrj }
611*38fd1498Szrj
612*38fd1498Szrj /* Return true if there is a compare_and_swap pattern. */
613*38fd1498Szrj
614*38fd1498Szrj bool
can_compare_and_swap_p(machine_mode mode,bool allow_libcall)615*38fd1498Szrj can_compare_and_swap_p (machine_mode mode, bool allow_libcall)
616*38fd1498Szrj {
617*38fd1498Szrj enum insn_code icode;
618*38fd1498Szrj
619*38fd1498Szrj /* Check for __atomic_compare_and_swap. */
620*38fd1498Szrj icode = direct_optab_handler (atomic_compare_and_swap_optab, mode);
621*38fd1498Szrj if (icode != CODE_FOR_nothing)
622*38fd1498Szrj return true;
623*38fd1498Szrj
624*38fd1498Szrj /* Check for __sync_compare_and_swap. */
625*38fd1498Szrj icode = optab_handler (sync_compare_and_swap_optab, mode);
626*38fd1498Szrj if (icode != CODE_FOR_nothing)
627*38fd1498Szrj return true;
628*38fd1498Szrj if (allow_libcall && optab_libfunc (sync_compare_and_swap_optab, mode))
629*38fd1498Szrj return true;
630*38fd1498Szrj
631*38fd1498Szrj /* No inline compare and swap. */
632*38fd1498Szrj return false;
633*38fd1498Szrj }
634*38fd1498Szrj
635*38fd1498Szrj /* Return true if an atomic exchange can be performed. */
636*38fd1498Szrj
637*38fd1498Szrj bool
can_atomic_exchange_p(machine_mode mode,bool allow_libcall)638*38fd1498Szrj can_atomic_exchange_p (machine_mode mode, bool allow_libcall)
639*38fd1498Szrj {
640*38fd1498Szrj enum insn_code icode;
641*38fd1498Szrj
642*38fd1498Szrj /* Check for __atomic_exchange. */
643*38fd1498Szrj icode = direct_optab_handler (atomic_exchange_optab, mode);
644*38fd1498Szrj if (icode != CODE_FOR_nothing)
645*38fd1498Szrj return true;
646*38fd1498Szrj
647*38fd1498Szrj /* Don't check __sync_test_and_set, as on some platforms that
648*38fd1498Szrj has reduced functionality. Targets that really do support
649*38fd1498Szrj a proper exchange should simply be updated to the __atomics. */
650*38fd1498Szrj
651*38fd1498Szrj return can_compare_and_swap_p (mode, allow_libcall);
652*38fd1498Szrj }
653*38fd1498Szrj
654*38fd1498Szrj /* Return true if an atomic load can be performed without falling back to
655*38fd1498Szrj a compare-and-swap. */
656*38fd1498Szrj
657*38fd1498Szrj bool
can_atomic_load_p(machine_mode mode)658*38fd1498Szrj can_atomic_load_p (machine_mode mode)
659*38fd1498Szrj {
660*38fd1498Szrj enum insn_code icode;
661*38fd1498Szrj
662*38fd1498Szrj /* Does the target supports the load directly? */
663*38fd1498Szrj icode = direct_optab_handler (atomic_load_optab, mode);
664*38fd1498Szrj if (icode != CODE_FOR_nothing)
665*38fd1498Szrj return true;
666*38fd1498Szrj
667*38fd1498Szrj /* If the size of the object is greater than word size on this target,
668*38fd1498Szrj then we assume that a load will not be atomic. Also see
669*38fd1498Szrj expand_atomic_load. */
670*38fd1498Szrj return known_le (GET_MODE_PRECISION (mode), BITS_PER_WORD);
671*38fd1498Szrj }
672*38fd1498Szrj
673*38fd1498Szrj /* Determine whether "1 << x" is relatively cheap in word_mode. */
674*38fd1498Szrj
675*38fd1498Szrj bool
lshift_cheap_p(bool speed_p)676*38fd1498Szrj lshift_cheap_p (bool speed_p)
677*38fd1498Szrj {
678*38fd1498Szrj /* FIXME: This should be made target dependent via this "this_target"
679*38fd1498Szrj mechanism, similar to e.g. can_copy_init_p in gcse.c. */
680*38fd1498Szrj static bool init[2] = { false, false };
681*38fd1498Szrj static bool cheap[2] = { true, true };
682*38fd1498Szrj
683*38fd1498Szrj /* If the targer has no lshift in word_mode, the operation will most
684*38fd1498Szrj probably not be cheap. ??? Does GCC even work for such targets? */
685*38fd1498Szrj if (optab_handler (ashl_optab, word_mode) == CODE_FOR_nothing)
686*38fd1498Szrj return false;
687*38fd1498Szrj
688*38fd1498Szrj if (!init[speed_p])
689*38fd1498Szrj {
690*38fd1498Szrj rtx reg = gen_raw_REG (word_mode, 10000);
691*38fd1498Szrj int cost = set_src_cost (gen_rtx_ASHIFT (word_mode, const1_rtx, reg),
692*38fd1498Szrj word_mode, speed_p);
693*38fd1498Szrj cheap[speed_p] = cost < COSTS_N_INSNS (3);
694*38fd1498Szrj init[speed_p] = true;
695*38fd1498Szrj }
696*38fd1498Szrj
697*38fd1498Szrj return cheap[speed_p];
698*38fd1498Szrj }
699*38fd1498Szrj
700*38fd1498Szrj /* Return true if optab OP supports at least one mode. */
701*38fd1498Szrj
702*38fd1498Szrj static bool
supports_at_least_one_mode_p(optab op)703*38fd1498Szrj supports_at_least_one_mode_p (optab op)
704*38fd1498Szrj {
705*38fd1498Szrj for (int i = 0; i < NUM_MACHINE_MODES; ++i)
706*38fd1498Szrj if (direct_optab_handler (op, (machine_mode) i) != CODE_FOR_nothing)
707*38fd1498Szrj return true;
708*38fd1498Szrj
709*38fd1498Szrj return false;
710*38fd1498Szrj }
711*38fd1498Szrj
712*38fd1498Szrj /* Return true if vec_gather_load is available for at least one vector
713*38fd1498Szrj mode. */
714*38fd1498Szrj
715*38fd1498Szrj bool
supports_vec_gather_load_p()716*38fd1498Szrj supports_vec_gather_load_p ()
717*38fd1498Szrj {
718*38fd1498Szrj if (this_fn_optabs->supports_vec_gather_load_cached)
719*38fd1498Szrj return this_fn_optabs->supports_vec_gather_load;
720*38fd1498Szrj
721*38fd1498Szrj this_fn_optabs->supports_vec_gather_load_cached = true;
722*38fd1498Szrj
723*38fd1498Szrj this_fn_optabs->supports_vec_gather_load
724*38fd1498Szrj = supports_at_least_one_mode_p (gather_load_optab);
725*38fd1498Szrj
726*38fd1498Szrj return this_fn_optabs->supports_vec_gather_load;
727*38fd1498Szrj }
728*38fd1498Szrj
729*38fd1498Szrj /* Return true if vec_scatter_store is available for at least one vector
730*38fd1498Szrj mode. */
731*38fd1498Szrj
732*38fd1498Szrj bool
supports_vec_scatter_store_p()733*38fd1498Szrj supports_vec_scatter_store_p ()
734*38fd1498Szrj {
735*38fd1498Szrj if (this_fn_optabs->supports_vec_scatter_store_cached)
736*38fd1498Szrj return this_fn_optabs->supports_vec_scatter_store;
737*38fd1498Szrj
738*38fd1498Szrj this_fn_optabs->supports_vec_scatter_store_cached = true;
739*38fd1498Szrj
740*38fd1498Szrj this_fn_optabs->supports_vec_scatter_store
741*38fd1498Szrj = supports_at_least_one_mode_p (scatter_store_optab);
742*38fd1498Szrj
743*38fd1498Szrj return this_fn_optabs->supports_vec_scatter_store;
744*38fd1498Szrj }
745*38fd1498Szrj
746