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