Branch data Line data Source code
1 : : /* IR-agnostic target query functions relating to optabs
2 : : Copyright (C) 2001-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify
7 : : it under the terms of the GNU General Public License as published by
8 : : the Free Software Foundation; either version 3, or (at your option)
9 : : any later version.
10 : :
11 : : GCC is distributed in the hope that it will be useful,
12 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : : GNU General Public License for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #ifndef GCC_OPTABS_QUERY_H
21 : : #define GCC_OPTABS_QUERY_H
22 : :
23 : : #include "insn-opinit.h"
24 : : #include "target.h"
25 : :
26 : : /* Return true if OP is a conversion optab. */
27 : :
28 : : inline bool
29 : 25156773 : convert_optab_p (optab op)
30 : : {
31 : 25156773 : return op > unknown_optab && op <= LAST_CONV_OPTAB;
32 : : }
33 : :
34 : : /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
35 : : if the target does not have such an insn. */
36 : :
37 : : inline enum insn_code
38 : 230890189 : optab_handler (optab op, machine_mode mode)
39 : : {
40 : 230890189 : unsigned scode = (op << 20) | mode;
41 : 92558424 : gcc_assert (op > LAST_CONV_OPTAB);
42 : 230890189 : return raw_optab_handler (scode);
43 : : }
44 : :
45 : : /* Return the insn used to perform conversion OP from mode FROM_MODE
46 : : to mode TO_MODE; return CODE_FOR_nothing if the target does not have
47 : : such an insn. */
48 : :
49 : : inline enum insn_code
50 : 12367683 : convert_optab_handler (convert_optab op, machine_mode to_mode,
51 : : machine_mode from_mode)
52 : : {
53 : 12367683 : unsigned scode = (op << 20) | (from_mode << 10) | to_mode;
54 : 12108619 : gcc_assert (convert_optab_p (op));
55 : 12118336 : return raw_optab_handler (scode);
56 : : }
57 : :
58 : : enum insn_code convert_optab_handler (convert_optab, machine_mode,
59 : : machine_mode, optimization_type);
60 : :
61 : : /* Return the insn used to implement mode MODE of OP, or CODE_FOR_nothing
62 : : if the target does not have such an insn. */
63 : :
64 : : inline enum insn_code
65 : 17042801 : direct_optab_handler (direct_optab op, machine_mode mode)
66 : : {
67 : 16912560 : return optab_handler (op, mode);
68 : : }
69 : :
70 : : enum insn_code direct_optab_handler (convert_optab, machine_mode,
71 : : optimization_type);
72 : :
73 : : /* Return true if UNOPTAB is for a trapping-on-overflow operation. */
74 : :
75 : : inline bool
76 : 36646 : trapv_unoptab_p (optab unoptab)
77 : : {
78 : 36646 : return (unoptab == negv_optab
79 : 36646 : || unoptab == absv_optab);
80 : : }
81 : :
82 : : /* Return true if BINOPTAB is for a trapping-on-overflow operation. */
83 : :
84 : : inline bool
85 : 66774 : trapv_binoptab_p (optab binoptab)
86 : : {
87 : 66774 : return (binoptab == addv_optab
88 : 66774 : || binoptab == subv_optab
89 : 66774 : || binoptab == smulv_optab);
90 : : }
91 : :
92 : : /* Return insn code for a comparison operator with VMODE
93 : : resultin MASK_MODE, unsigned if UNS is true. */
94 : :
95 : : inline enum insn_code
96 : 1085634 : get_vec_cmp_icode (machine_mode vmode, machine_mode mask_mode, bool uns)
97 : : {
98 : 1085634 : optab tab = uns ? vec_cmpu_optab : vec_cmp_optab;
99 : 1085634 : return convert_optab_handler (tab, vmode, mask_mode);
100 : : }
101 : :
102 : : /* Return insn code for a comparison operator with VMODE
103 : : resultin MASK_MODE (only for EQ/NE). */
104 : :
105 : : inline enum insn_code
106 : 159117 : get_vec_cmp_eq_icode (machine_mode vmode, machine_mode mask_mode)
107 : : {
108 : 159117 : return convert_optab_handler (vec_cmpeq_optab, vmode, mask_mode);
109 : : }
110 : :
111 : : /* Return insn code for a conditional operator with a comparison in
112 : : mode CMODE, unsigned if UNS is true, resulting in a value of mode VMODE. */
113 : :
114 : : inline enum insn_code
115 : 70563 : get_vcond_icode (machine_mode vmode, machine_mode cmode, bool uns)
116 : : {
117 : 70563 : enum insn_code icode = CODE_FOR_nothing;
118 : 70563 : if (uns)
119 : 15150 : icode = convert_optab_handler (vcondu_optab, vmode, cmode);
120 : : else
121 : 55413 : icode = convert_optab_handler (vcond_optab, vmode, cmode);
122 : 70563 : return icode;
123 : : }
124 : :
125 : : /* Return insn code for a conditional operator with a mask mode
126 : : MMODE resulting in a value of mode VMODE. */
127 : :
128 : : inline enum insn_code
129 : 19282 : get_vcond_mask_icode (machine_mode vmode, machine_mode mmode)
130 : : {
131 : 19282 : return convert_optab_handler (vcond_mask_optab, vmode, mmode);
132 : : }
133 : :
134 : : /* Return insn code for a conditional operator with a comparison in
135 : : mode CMODE (only EQ/NE), resulting in a value of mode VMODE. */
136 : :
137 : : inline enum insn_code
138 : 12438 : get_vcond_eq_icode (machine_mode vmode, machine_mode cmode)
139 : : {
140 : 12438 : return convert_optab_handler (vcondeq_optab, vmode, cmode);
141 : : }
142 : :
143 : : /* Enumerates the possible extraction_insn operations. */
144 : : enum extraction_pattern { EP_insv, EP_extv, EP_extzv };
145 : :
146 : : /* Describes an instruction that inserts or extracts a bitfield. */
147 : : class extraction_insn
148 : : {
149 : : public:
150 : : /* The code of the instruction. */
151 : : enum insn_code icode;
152 : :
153 : : /* The mode that the structure operand should have. This is byte_mode
154 : : when using the legacy insv, extv and extzv patterns to access memory.
155 : : If no mode is given, the structure is a BLKmode memory. */
156 : : opt_scalar_int_mode struct_mode;
157 : :
158 : : /* The mode of the field to be inserted or extracted, and by extension
159 : : the mode of the insertion or extraction itself. */
160 : : scalar_int_mode field_mode;
161 : :
162 : : /* The mode of the field's bit position. This is only important
163 : : when the position is variable rather than constant. */
164 : : scalar_int_mode pos_mode;
165 : : };
166 : :
167 : : bool get_best_reg_extraction_insn (extraction_insn *,
168 : : enum extraction_pattern,
169 : : unsigned HOST_WIDE_INT, machine_mode);
170 : : bool get_best_mem_extraction_insn (extraction_insn *,
171 : : enum extraction_pattern,
172 : : HOST_WIDE_INT, HOST_WIDE_INT, machine_mode);
173 : :
174 : : enum insn_code can_extend_p (machine_mode, machine_mode, int);
175 : : enum insn_code can_float_p (machine_mode, machine_mode, int);
176 : : enum insn_code can_fix_p (machine_mode, machine_mode, int, bool *);
177 : : bool can_conditionally_move_p (machine_mode mode);
178 : : opt_machine_mode qimode_for_vec_perm (machine_mode);
179 : : bool selector_fits_mode_p (machine_mode, const vec_perm_indices &);
180 : : bool can_vec_perm_var_p (machine_mode);
181 : : bool can_vec_perm_const_p (machine_mode, machine_mode,
182 : : const vec_perm_indices &, bool = true);
183 : : /* Find a widening optab even if it doesn't widen as much as we want. */
184 : : #define find_widening_optab_handler(A, B, C) \
185 : : find_widening_optab_handler_and_mode (A, B, C, NULL)
186 : : enum insn_code find_widening_optab_handler_and_mode (optab, machine_mode,
187 : : machine_mode,
188 : : machine_mode *);
189 : : int can_mult_highpart_p (machine_mode, bool);
190 : : bool can_compare_and_swap_p (machine_mode, bool);
191 : : bool can_atomic_exchange_p (machine_mode, bool);
192 : : bool can_atomic_load_p (machine_mode);
193 : : bool lshift_cheap_p (bool);
194 : : bool supports_vec_gather_load_p (machine_mode = E_VOIDmode);
195 : : bool supports_vec_scatter_store_p (machine_mode = E_VOIDmode);
196 : : bool can_vec_extract (machine_mode, machine_mode);
197 : :
198 : : /* Version of find_widening_optab_handler_and_mode that operates on
199 : : specific mode types. */
200 : :
201 : : template<typename T>
202 : : inline enum insn_code
203 : 208415 : find_widening_optab_handler_and_mode (optab op, const T &to_mode,
204 : : const T &from_mode, T *found_mode)
205 : : {
206 : : machine_mode tmp;
207 : : enum insn_code icode = find_widening_optab_handler_and_mode
208 : 208415 : (op, machine_mode (to_mode), machine_mode (from_mode), &tmp);
209 : 208415 : if (icode != CODE_FOR_nothing && found_mode)
210 : 10162 : *found_mode = as_a <T> (tmp);
211 : 208415 : return icode;
212 : : }
213 : :
214 : : #endif
|