annotate gcc/optabs-query.c @ 158:494b0b89df80 default tip

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