]> gcc.gnu.org Git - gcc.git/blame - gcc/optabs-tree.cc
Daily bump.
[gcc.git] / gcc / optabs-tree.cc
CommitLineData
385399a8 1/* Tree-based target query functions relating to optabs
aeee4812 2 Copyright (C) 1987-2023 Free Software Foundation, Inc.
385399a8
RS
3
4This file is part of GCC.
5
6GCC is free software; you can redistribute it and/or modify it under
7the terms of the GNU General Public License as published by the Free
8Software Foundation; either version 3, or (at your option) any later
9version.
10
11GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12WARRANTY; without even the implied warranty of MERCHANTABILITY or
13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14for more details.
15
16You should have received a copy of the GNU General Public License
17along with GCC; see the file COPYING3. If not see
18<http://www.gnu.org/licenses/>. */
19
20
21#include "config.h"
22#include "system.h"
23#include "coretypes.h"
24#include "target.h"
25#include "insn-codes.h"
dcd2ca63 26#include "rtl.h"
385399a8 27#include "tree.h"
dcd2ca63
IL
28#include "memmodel.h"
29#include "optabs.h"
385399a8
RS
30#include "optabs-tree.h"
31#include "stor-layout.h"
32
33/* Return the optab used for computing the operation given by the tree code,
34 CODE and the tree EXP. This function is not always usable (for example, it
35 cannot give complete results for multiplication or division) but probably
36 ought to be relied on more widely throughout the expander. */
37optab
38optab_for_tree_code (enum tree_code code, const_tree type,
39 enum optab_subtype subtype)
40{
41 bool trapv;
42 switch (code)
43 {
44 case BIT_AND_EXPR:
45 return and_optab;
46
47 case BIT_IOR_EXPR:
48 return ior_optab;
49
50 case BIT_NOT_EXPR:
51 return one_cmpl_optab;
52
53 case BIT_XOR_EXPR:
54 return xor_optab;
55
56 case MULT_HIGHPART_EXPR:
57 return TYPE_UNSIGNED (type) ? umul_highpart_optab : smul_highpart_optab;
58
385399a8
RS
59 case CEIL_MOD_EXPR:
60 case FLOOR_MOD_EXPR:
61 case ROUND_MOD_EXPR:
ffc7f200
JJ
62 /* {s,u}mod_optab implements TRUNC_MOD_EXPR. For scalar modes,
63 expansion has code to adjust TRUNC_MOD_EXPR into the desired other
64 modes, but for vector modes it does not. The adjustment code
65 should be instead emitted in tree-vect-patterns.cc. */
66 if (TREE_CODE (type) == VECTOR_TYPE)
67 return unknown_optab;
68 /* FALLTHRU */
69 case TRUNC_MOD_EXPR:
385399a8
RS
70 return TYPE_UNSIGNED (type) ? umod_optab : smod_optab;
71
385399a8
RS
72 case CEIL_DIV_EXPR:
73 case FLOOR_DIV_EXPR:
74 case ROUND_DIV_EXPR:
ffc7f200
JJ
75 /* {,u}{s,u}div_optab implements {TRUNC,EXACT}_DIV_EXPR or RDIV_EXPR.
76 For scalar modes, expansion has code to adjust TRUNC_DIV_EXPR
77 into the desired other modes, but for vector modes it does not.
78 The adjustment code should be instead emitted in
79 tree-vect-patterns.cc. */
80 if (TREE_CODE (type) == VECTOR_TYPE)
81 return unknown_optab;
82 /* FALLTHRU */
83 case RDIV_EXPR:
84 case TRUNC_DIV_EXPR:
385399a8
RS
85 case EXACT_DIV_EXPR:
86 if (TYPE_SATURATING (type))
87 return TYPE_UNSIGNED (type) ? usdiv_optab : ssdiv_optab;
88 return TYPE_UNSIGNED (type) ? udiv_optab : sdiv_optab;
89
90 case LSHIFT_EXPR:
91 if (TREE_CODE (type) == VECTOR_TYPE)
92 {
93 if (subtype == optab_vector)
94 return TYPE_SATURATING (type) ? unknown_optab : vashl_optab;
95
96 gcc_assert (subtype == optab_scalar);
97 }
98 if (TYPE_SATURATING (type))
99 return TYPE_UNSIGNED (type) ? usashl_optab : ssashl_optab;
100 return ashl_optab;
101
102 case RSHIFT_EXPR:
103 if (TREE_CODE (type) == VECTOR_TYPE)
104 {
105 if (subtype == optab_vector)
106 return TYPE_UNSIGNED (type) ? vlshr_optab : vashr_optab;
107
108 gcc_assert (subtype == optab_scalar);
109 }
110 return TYPE_UNSIGNED (type) ? lshr_optab : ashr_optab;
111
112 case LROTATE_EXPR:
113 if (TREE_CODE (type) == VECTOR_TYPE)
114 {
115 if (subtype == optab_vector)
116 return vrotl_optab;
117
118 gcc_assert (subtype == optab_scalar);
119 }
120 return rotl_optab;
121
122 case RROTATE_EXPR:
123 if (TREE_CODE (type) == VECTOR_TYPE)
124 {
125 if (subtype == optab_vector)
126 return vrotr_optab;
127
128 gcc_assert (subtype == optab_scalar);
129 }
130 return rotr_optab;
131
132 case MAX_EXPR:
133 return TYPE_UNSIGNED (type) ? umax_optab : smax_optab;
134
135 case MIN_EXPR:
136 return TYPE_UNSIGNED (type) ? umin_optab : smin_optab;
137
138 case REALIGN_LOAD_EXPR:
139 return vec_realign_load_optab;
140
141 case WIDEN_SUM_EXPR:
142 return TYPE_UNSIGNED (type) ? usum_widen_optab : ssum_widen_optab;
143
144 case DOT_PROD_EXPR:
ab0a6b21
TC
145 {
146 if (subtype == optab_vector_mixed_sign)
147 return usdot_prod_optab;
148
149 return (TYPE_UNSIGNED (type) ? udot_prod_optab : sdot_prod_optab);
150 }
385399a8
RS
151
152 case SAD_EXPR:
153 return TYPE_UNSIGNED (type) ? usad_optab : ssad_optab;
154
155 case WIDEN_MULT_PLUS_EXPR:
156 return (TYPE_UNSIGNED (type)
157 ? (TYPE_SATURATING (type)
158 ? usmadd_widen_optab : umadd_widen_optab)
159 : (TYPE_SATURATING (type)
160 ? ssmadd_widen_optab : smadd_widen_optab));
161
162 case WIDEN_MULT_MINUS_EXPR:
163 return (TYPE_UNSIGNED (type)
164 ? (TYPE_SATURATING (type)
165 ? usmsub_widen_optab : umsub_widen_optab)
166 : (TYPE_SATURATING (type)
167 ? ssmsub_widen_optab : smsub_widen_optab));
168
385399a8 169 case VEC_WIDEN_MULT_HI_EXPR:
1bda738b
JJ
170 return (TYPE_UNSIGNED (type)
171 ? vec_widen_umult_hi_optab : vec_widen_smult_hi_optab);
385399a8
RS
172
173 case VEC_WIDEN_MULT_LO_EXPR:
1bda738b
JJ
174 return (TYPE_UNSIGNED (type)
175 ? vec_widen_umult_lo_optab : vec_widen_smult_lo_optab);
385399a8
RS
176
177 case VEC_WIDEN_MULT_EVEN_EXPR:
1bda738b
JJ
178 return (TYPE_UNSIGNED (type)
179 ? vec_widen_umult_even_optab : vec_widen_smult_even_optab);
385399a8
RS
180
181 case VEC_WIDEN_MULT_ODD_EXPR:
1bda738b
JJ
182 return (TYPE_UNSIGNED (type)
183 ? vec_widen_umult_odd_optab : vec_widen_smult_odd_optab);
385399a8
RS
184
185 case VEC_WIDEN_LSHIFT_HI_EXPR:
1bda738b
JJ
186 return (TYPE_UNSIGNED (type)
187 ? vec_widen_ushiftl_hi_optab : vec_widen_sshiftl_hi_optab);
385399a8
RS
188
189 case VEC_WIDEN_LSHIFT_LO_EXPR:
1bda738b
JJ
190 return (TYPE_UNSIGNED (type)
191 ? vec_widen_ushiftl_lo_optab : vec_widen_sshiftl_lo_optab);
385399a8 192
9fc9573f
JH
193 case VEC_WIDEN_PLUS_LO_EXPR:
194 return (TYPE_UNSIGNED (type)
195 ? vec_widen_uaddl_lo_optab : vec_widen_saddl_lo_optab);
196
197 case VEC_WIDEN_PLUS_HI_EXPR:
198 return (TYPE_UNSIGNED (type)
199 ? vec_widen_uaddl_hi_optab : vec_widen_saddl_hi_optab);
200
201 case VEC_WIDEN_MINUS_LO_EXPR:
202 return (TYPE_UNSIGNED (type)
203 ? vec_widen_usubl_lo_optab : vec_widen_ssubl_lo_optab);
204
205 case VEC_WIDEN_MINUS_HI_EXPR:
206 return (TYPE_UNSIGNED (type)
207 ? vec_widen_usubl_hi_optab : vec_widen_ssubl_hi_optab);
208
385399a8 209 case VEC_UNPACK_HI_EXPR:
1bda738b
JJ
210 return (TYPE_UNSIGNED (type)
211 ? vec_unpacku_hi_optab : vec_unpacks_hi_optab);
385399a8
RS
212
213 case VEC_UNPACK_LO_EXPR:
1bda738b
JJ
214 return (TYPE_UNSIGNED (type)
215 ? vec_unpacku_lo_optab : vec_unpacks_lo_optab);
385399a8
RS
216
217 case VEC_UNPACK_FLOAT_HI_EXPR:
218 /* The signedness is determined from input operand. */
1bda738b
JJ
219 return (TYPE_UNSIGNED (type)
220 ? vec_unpacku_float_hi_optab : vec_unpacks_float_hi_optab);
385399a8
RS
221
222 case VEC_UNPACK_FLOAT_LO_EXPR:
223 /* The signedness is determined from input operand. */
1bda738b
JJ
224 return (TYPE_UNSIGNED (type)
225 ? vec_unpacku_float_lo_optab : vec_unpacks_float_lo_optab);
226
227 case VEC_UNPACK_FIX_TRUNC_HI_EXPR:
228 /* The signedness is determined from output operand. */
229 return (TYPE_UNSIGNED (type)
230 ? vec_unpack_ufix_trunc_hi_optab
231 : vec_unpack_sfix_trunc_hi_optab);
232
233 case VEC_UNPACK_FIX_TRUNC_LO_EXPR:
234 /* The signedness is determined from output operand. */
235 return (TYPE_UNSIGNED (type)
236 ? vec_unpack_ufix_trunc_lo_optab
237 : vec_unpack_sfix_trunc_lo_optab);
385399a8
RS
238
239 case VEC_PACK_TRUNC_EXPR:
240 return vec_pack_trunc_optab;
241
242 case VEC_PACK_SAT_EXPR:
243 return TYPE_UNSIGNED (type) ? vec_pack_usat_optab : vec_pack_ssat_optab;
244
245 case VEC_PACK_FIX_TRUNC_EXPR:
246 /* The signedness is determined from output operand. */
1bda738b
JJ
247 return (TYPE_UNSIGNED (type)
248 ? vec_pack_ufix_trunc_optab : vec_pack_sfix_trunc_optab);
249
250 case VEC_PACK_FLOAT_EXPR:
251 /* The signedness is determined from input operand. */
252 return (TYPE_UNSIGNED (type)
253 ? vec_packu_float_optab : vec_packs_float_optab);
385399a8 254
be4c1d4a
RS
255 case VEC_DUPLICATE_EXPR:
256 return vec_duplicate_optab;
257
9adab579
RS
258 case VEC_SERIES_EXPR:
259 return vec_series_optab;
260
385399a8
RS
261 default:
262 break;
263 }
264
265 trapv = INTEGRAL_TYPE_P (type) && TYPE_OVERFLOW_TRAPS (type);
266 switch (code)
267 {
268 case POINTER_PLUS_EXPR:
269 case PLUS_EXPR:
270 if (TYPE_SATURATING (type))
271 return TYPE_UNSIGNED (type) ? usadd_optab : ssadd_optab;
272 return trapv ? addv_optab : add_optab;
273
1af4ebf5 274 case POINTER_DIFF_EXPR:
385399a8
RS
275 case MINUS_EXPR:
276 if (TYPE_SATURATING (type))
277 return TYPE_UNSIGNED (type) ? ussub_optab : sssub_optab;
278 return trapv ? subv_optab : sub_optab;
279
280 case MULT_EXPR:
281 if (TYPE_SATURATING (type))
282 return TYPE_UNSIGNED (type) ? usmul_optab : ssmul_optab;
283 return trapv ? smulv_optab : smul_optab;
284
285 case NEGATE_EXPR:
286 if (TYPE_SATURATING (type))
287 return TYPE_UNSIGNED (type) ? usneg_optab : ssneg_optab;
288 return trapv ? negv_optab : neg_optab;
289
290 case ABS_EXPR:
291 return trapv ? absv_optab : abs_optab;
292
e197e64e
KV
293 case ABSU_EXPR:
294 return abs_optab;
385399a8
RS
295 default:
296 return unknown_optab;
297 }
298}
299
4af29981
JH
300/* Check whether an operation represented by CODE is a 'half' widening operation
301 in which the input vector type has half the number of bits of the output
302 vector type e.g. V8QI->V8HI.
303
304 This is handled by widening the inputs using NOP_EXPRs then using a
305 non-widening stmt e.g. MINUS_EXPR. RTL fusing converts these to the widening
306 hardware instructions if supported.
307
308 The more typical case (handled in supportable_widening_operation) is where
309 the input vector type has the same number of bits as the output vector type.
310 In this case half the elements of the input vectors must be processed at a
311 time into respective vector outputs with elements twice as wide i.e. a
312 'hi'/'lo' pair using codes such as VEC_WIDEN_MINUS_HI/LO.
313
314 Supported widening operations:
315 WIDEN_MINUS_EXPR
316 WIDEN_PLUS_EXPR
317 WIDEN_MULT_EXPR
318 WIDEN_LSHIFT_EXPR
319
320 Output:
321 - CODE1 - The non-widened code, which will be used after the inputs are
322 converted to the wide type. */
323bool
324supportable_half_widening_operation (enum tree_code code, tree vectype_out,
325 tree vectype_in, enum tree_code *code1)
326{
327 machine_mode m1,m2;
328 enum tree_code dummy_code;
329 optab op;
330
331 gcc_assert (VECTOR_TYPE_P (vectype_out) && VECTOR_TYPE_P (vectype_in));
332
333 m1 = TYPE_MODE (vectype_out);
334 m2 = TYPE_MODE (vectype_in);
335
336 if (!VECTOR_MODE_P (m1) || !VECTOR_MODE_P (m2))
337 return false;
338
339 if (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype_in),
340 TYPE_VECTOR_SUBPARTS (vectype_out)))
341 return false;
342
343 switch (code)
344 {
345 case WIDEN_LSHIFT_EXPR:
346 *code1 = LSHIFT_EXPR;
347 break;
348 case WIDEN_MINUS_EXPR:
349 *code1 = MINUS_EXPR;
350 break;
351 case WIDEN_PLUS_EXPR:
352 *code1 = PLUS_EXPR;
353 break;
354 case WIDEN_MULT_EXPR:
355 *code1 = MULT_EXPR;
356 break;
357 default:
358 return false;
359 }
360
361 if (!supportable_convert_operation (NOP_EXPR, vectype_out, vectype_in,
362 &dummy_code))
363 return false;
364
365 op = optab_for_tree_code (*code1, vectype_out, optab_vector);
366 return (optab_handler (op, TYPE_MODE (vectype_out)) != CODE_FOR_nothing);
367}
368
385399a8
RS
369/* Function supportable_convert_operation
370
371 Check whether an operation represented by the code CODE is a
372 convert operation that is supported by the target platform in
373 vector form (i.e., when operating on arguments of type VECTYPE_IN
374 producing a result of type VECTYPE_OUT).
375
376 Convert operations we currently support directly are FIX_TRUNC and FLOAT.
377 This function checks if these operations are supported
477daf83 378 by the target platform directly (via vector tree-codes).
385399a8
RS
379
380 Output:
381 - CODE1 is code of vector operation to be used when
477daf83 382 vectorizing the operation, if available. */
385399a8
RS
383
384bool
385supportable_convert_operation (enum tree_code code,
386 tree vectype_out, tree vectype_in,
477daf83 387 enum tree_code *code1)
385399a8
RS
388{
389 machine_mode m1,m2;
390 bool truncp;
391
b6268016
RS
392 gcc_assert (VECTOR_TYPE_P (vectype_out) && VECTOR_TYPE_P (vectype_in));
393
385399a8
RS
394 m1 = TYPE_MODE (vectype_out);
395 m2 = TYPE_MODE (vectype_in);
396
b6268016
RS
397 if (!VECTOR_MODE_P (m1) || !VECTOR_MODE_P (m2))
398 return false;
399
385399a8
RS
400 /* First check if we can done conversion directly. */
401 if ((code == FIX_TRUNC_EXPR
402 && can_fix_p (m1,m2,TYPE_UNSIGNED (vectype_out), &truncp)
403 != CODE_FOR_nothing)
404 || (code == FLOAT_EXPR
405 && can_float_p (m1,m2,TYPE_UNSIGNED (vectype_in))
406 != CODE_FOR_nothing))
407 {
408 *code1 = code;
409 return true;
410 }
411
9c437a10
RS
412 if (GET_MODE_UNIT_PRECISION (m1) > GET_MODE_UNIT_PRECISION (m2)
413 && can_extend_p (m1, m2, TYPE_UNSIGNED (vectype_in)))
414 {
415 *code1 = code;
416 return true;
417 }
418
419 if (GET_MODE_UNIT_PRECISION (m1) < GET_MODE_UNIT_PRECISION (m2)
420 && convert_optab_handler (trunc_optab, m1, m2) != CODE_FOR_nothing)
421 {
422 *code1 = code;
423 return true;
424 }
425
385399a8
RS
426 return false;
427}
428
3940daff
IL
429/* Return true iff vec_cmp_optab/vec_cmpu_optab can handle a vector comparison
430 for code CODE, comparing operands of type VALUE_TYPE and producing a result
431 of type MASK_TYPE. */
432
433static bool
434vec_cmp_icode_p (tree value_type, tree mask_type, enum tree_code code)
435{
436 enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (value_type));
437 if (rcode == UNKNOWN)
438 return false;
439
440 return can_vec_cmp_compare_p (rcode, TYPE_MODE (value_type),
441 TYPE_MODE (mask_type));
442}
443
444/* Return true iff vec_cmpeq_optab can handle a vector comparison for code
445 CODE, comparing operands of type VALUE_TYPE and producing a result of type
446 MASK_TYPE. */
447
448static bool
449vec_cmp_eq_icode_p (tree value_type, tree mask_type, enum tree_code code)
450{
451 if (code != EQ_EXPR && code != NE_EXPR)
452 return false;
453
454 return get_vec_cmp_eq_icode (TYPE_MODE (value_type), TYPE_MODE (mask_type))
455 != CODE_FOR_nothing;
456}
457
42fd8198
IE
458/* Return TRUE if appropriate vector insn is available
459 for vector comparison expr with vector type VALUE_TYPE
460 and resulting mask with MASK_TYPE. */
461
462bool
96592eed 463expand_vec_cmp_expr_p (tree value_type, tree mask_type, enum tree_code code)
42fd8198 464{
3940daff
IL
465 return vec_cmp_icode_p (value_type, mask_type, code)
466 || vec_cmp_eq_icode_p (value_type, mask_type, code);
42fd8198
IE
467}
468
dcd2ca63
IL
469/* Return true iff vcond_optab/vcondu_optab can handle a vector
470 comparison for code CODE, comparing operands of type CMP_OP_TYPE and
471 producing a result of type VALUE_TYPE. */
472
473static bool
474vcond_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
475{
3940daff
IL
476 enum rtx_code rcode = get_rtx_code_1 (code, TYPE_UNSIGNED (cmp_op_type));
477 if (rcode == UNKNOWN)
478 return false;
479
480 return can_vcond_compare_p (rcode, TYPE_MODE (value_type),
481 TYPE_MODE (cmp_op_type));
dcd2ca63
IL
482}
483
484/* Return true iff vcondeq_optab can handle a vector comparison for code CODE,
485 comparing operands of type CMP_OP_TYPE and producing a result of type
486 VALUE_TYPE. */
487
488static bool
489vcond_eq_icode_p (tree value_type, tree cmp_op_type, enum tree_code code)
490{
491 if (code != EQ_EXPR && code != NE_EXPR)
492 return false;
493
494 return get_vcond_eq_icode (TYPE_MODE (value_type), TYPE_MODE (cmp_op_type))
495 != CODE_FOR_nothing;
496}
497
385399a8
RS
498/* Return TRUE iff, appropriate vector insns are available
499 for vector cond expr with vector type VALUE_TYPE and a comparison
500 with operand vector types in CMP_OP_TYPE. */
501
502bool
96592eed 503expand_vec_cond_expr_p (tree value_type, tree cmp_op_type, enum tree_code code)
385399a8
RS
504{
505 machine_mode value_mode = TYPE_MODE (value_type);
506 machine_mode cmp_op_mode = TYPE_MODE (cmp_op_type);
0d99886f
AP
507 if (VECTOR_BOOLEAN_TYPE_P (cmp_op_type)
508 && get_vcond_mask_icode (TYPE_MODE (value_type),
509 TYPE_MODE (cmp_op_type)) != CODE_FOR_nothing)
510 return true;
511
e29dd0eb 512 if (maybe_ne (GET_MODE_NUNITS (value_mode), GET_MODE_NUNITS (cmp_op_mode)))
385399a8 513 return false;
96592eed 514
dcd2ca63
IL
515 if (TREE_CODE_CLASS (code) != tcc_comparison)
516 /* This may happen, for example, if code == SSA_NAME, in which case we
517 cannot be certain whether a vector insn is available. */
96592eed
JJ
518 return false;
519
dcd2ca63
IL
520 return vcond_icode_p (value_type, cmp_op_type, code)
521 || vcond_eq_icode_p (value_type, cmp_op_type, code);
385399a8
RS
522}
523
524/* Use the current target and options to initialize
525 TREE_OPTIMIZATION_OPTABS (OPTNODE). */
526
527void
528init_tree_optimization_optabs (tree optnode)
529{
530 /* Quick exit if we have already computed optabs for this target. */
531 if (TREE_OPTIMIZATION_BASE_OPTABS (optnode) == this_target_optabs)
532 return;
533
534 /* Forget any previous information and set up for the current target. */
535 TREE_OPTIMIZATION_BASE_OPTABS (optnode) = this_target_optabs;
536 struct target_optabs *tmp_optabs = (struct target_optabs *)
537 TREE_OPTIMIZATION_OPTABS (optnode);
538 if (tmp_optabs)
539 memset (tmp_optabs, 0, sizeof (struct target_optabs));
540 else
bfaa08b7 541 tmp_optabs = ggc_cleared_alloc<target_optabs> ();
385399a8
RS
542
543 /* Generate a new set of optabs into tmp_optabs. */
544 init_all_optabs (tmp_optabs);
545
546 /* If the optabs changed, record it. */
547 if (memcmp (tmp_optabs, this_target_optabs, sizeof (struct target_optabs)))
548 TREE_OPTIMIZATION_OPTABS (optnode) = tmp_optabs;
549 else
550 {
551 TREE_OPTIMIZATION_OPTABS (optnode) = NULL;
552 ggc_free (tmp_optabs);
553 }
554}
71f82be9
JG
555
556/* Return TRUE if the target has support for vector right shift of an
557 operand of type TYPE. If OT_TYPE is OPTAB_DEFAULT, check for existence
558 of a shift by either a scalar or a vector. Otherwise, check only
559 for a shift that matches OT_TYPE. */
560
561bool
562target_supports_op_p (tree type, enum tree_code code,
563 enum optab_subtype ot_subtype)
564{
565 optab ot = optab_for_tree_code (code, type, ot_subtype);
566 return (ot != unknown_optab
567 && optab_handler (ot, TYPE_MODE (type)) != CODE_FOR_nothing);
568}
569
This page took 4.357937 seconds and 5 git commands to generate.