1 | /* Internal functions. |
2 | Copyright (C) 2011-2023 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 it under |
7 | the terms of the GNU General Public License as published by the Free |
8 | Software Foundation; either version 3, or (at your option) any later |
9 | version. |
10 | |
11 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
13 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
14 | 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_INTERNAL_FN_H |
21 | #define GCC_INTERNAL_FN_H |
22 | |
23 | #include "insn-codes.h" |
24 | #include "insn-opinit.h" |
25 | |
26 | |
27 | /* INTEGER_CST values for IFN_UNIQUE function arg-0. |
28 | |
29 | UNSPEC: Undifferentiated UNIQUE. |
30 | |
31 | FORK and JOIN mark the points at which OpenACC partitioned |
32 | execution is entered or exited. |
33 | DEP_VAR = UNIQUE ({FORK,JOIN}, DEP_VAR, AXIS) |
34 | |
35 | HEAD_MARK and TAIL_MARK are used to demark the sequence entering |
36 | or leaving partitioned execution. |
37 | DEP_VAR = UNIQUE ({HEAD,TAIL}_MARK, REMAINING_MARKS, ...PRIMARY_FLAGS) |
38 | |
39 | The PRIMARY_FLAGS only occur on the first HEAD_MARK of a sequence. |
40 | |
41 | PRIVATE captures variables to be made private at the surrounding parallelism |
42 | level. */ |
43 | #define IFN_UNIQUE_CODES \ |
44 | DEF(UNSPEC), \ |
45 | DEF(OACC_FORK), DEF(OACC_JOIN), \ |
46 | DEF(OACC_HEAD_MARK), DEF(OACC_TAIL_MARK), \ |
47 | DEF(OACC_PRIVATE) |
48 | |
49 | enum ifn_unique_kind { |
50 | #define DEF(X) IFN_UNIQUE_##X |
51 | IFN_UNIQUE_CODES |
52 | #undef DEF |
53 | }; |
54 | |
55 | /* INTEGER_CST values for IFN_GOACC_LOOP arg-0. Allows the precise |
56 | stepping of the compute geometry over the loop iterations to be |
57 | deferred until it is known which compiler is generating the code. |
58 | The action is encoded in a constant first argument. |
59 | |
60 | CHUNK_MAX = LOOP (CODE_CHUNKS, DIR, RANGE, STEP, CHUNK_SIZE, MASK) |
61 | STEP = LOOP (CODE_STEP, DIR, RANGE, STEP, CHUNK_SIZE, MASK) |
62 | OFFSET = LOOP (CODE_OFFSET, DIR, RANGE, STEP, CHUNK_SIZE, MASK, CHUNK_NO) |
63 | BOUND = LOOP (CODE_BOUND, DIR, RANGE, STEP, CHUNK_SIZE, MASK, OFFSET) |
64 | |
65 | DIR - +1 for up loop, -1 for down loop |
66 | RANGE - Range of loop (END - BASE) |
67 | STEP - iteration step size |
68 | CHUNKING - size of chunking, (constant zero for no chunking) |
69 | CHUNK_NO - chunk number |
70 | MASK - partitioning mask. */ |
71 | |
72 | #define IFN_GOACC_LOOP_CODES \ |
73 | DEF(CHUNKS), DEF(STEP), DEF(OFFSET), DEF(BOUND) |
74 | enum ifn_goacc_loop_kind { |
75 | #define DEF(X) IFN_GOACC_LOOP_##X |
76 | IFN_GOACC_LOOP_CODES |
77 | #undef DEF |
78 | }; |
79 | |
80 | /* The GOACC_REDUCTION function defines a generic interface to support |
81 | gang, worker and vector reductions. All calls are of the following |
82 | form: |
83 | |
84 | V = REDUCTION (CODE, REF_TO_RES, LOCAL_VAR, LEVEL, OP, OFFSET) |
85 | |
86 | REF_TO_RES - is a reference to the original reduction varl, may be NULL |
87 | LOCAL_VAR is the intermediate reduction variable |
88 | LEVEL corresponds to the GOMP_DIM of the reduction |
89 | OP is the tree code of the reduction operation |
90 | OFFSET may be used as an offset into a reduction array for the |
91 | reductions occuring at this level. |
92 | In general the return value is LOCAL_VAR, which creates a data |
93 | dependency between calls operating on the same reduction. */ |
94 | |
95 | #define IFN_GOACC_REDUCTION_CODES \ |
96 | DEF(SETUP), DEF(INIT), DEF(FINI), DEF(TEARDOWN) |
97 | enum ifn_goacc_reduction_kind { |
98 | #define DEF(X) IFN_GOACC_REDUCTION_##X |
99 | IFN_GOACC_REDUCTION_CODES |
100 | #undef DEF |
101 | }; |
102 | |
103 | /* Initialize internal function tables. */ |
104 | |
105 | extern void init_internal_fns (); |
106 | |
107 | /* Return the name of internal function FN. The name is only meaningful |
108 | for dumps; it has no linkage. */ |
109 | |
110 | extern const char *const internal_fn_name_array[]; |
111 | |
112 | inline const char * |
113 | internal_fn_name (enum internal_fn fn) |
114 | { |
115 | return internal_fn_name_array[(int) fn]; |
116 | } |
117 | |
118 | extern internal_fn lookup_internal_fn (const char *); |
119 | extern void lookup_hilo_internal_fn (internal_fn, internal_fn *, internal_fn *); |
120 | extern void lookup_evenodd_internal_fn (internal_fn, internal_fn *, |
121 | internal_fn *); |
122 | extern optab direct_internal_fn_optab (internal_fn, tree_pair); |
123 | |
124 | /* Return the ECF_* flags for function FN. */ |
125 | |
126 | extern const int internal_fn_flags_array[]; |
127 | |
128 | inline int |
129 | internal_fn_flags (enum internal_fn fn) |
130 | { |
131 | return internal_fn_flags_array[(int) fn]; |
132 | } |
133 | |
134 | /* Return fnspec for function FN. */ |
135 | |
136 | extern GTY(()) const_tree internal_fn_fnspec_array[IFN_LAST + 1]; |
137 | |
138 | inline const_tree |
139 | internal_fn_fnspec (enum internal_fn fn) |
140 | { |
141 | return internal_fn_fnspec_array[(int) fn]; |
142 | } |
143 | |
144 | /* Describes an internal function that maps directly to an optab. */ |
145 | struct direct_internal_fn_info |
146 | { |
147 | /* optabs can be parameterized by one or two modes. These fields describe |
148 | how to select those modes from the types of the return value and |
149 | arguments. A value of -1 says that the mode is determined by the |
150 | return type while a value N >= 0 says that the mode is determined by |
151 | the type of argument N. A value of -2 says that this internal |
152 | function isn't directly mapped to an optab. */ |
153 | signed int type0 : 8; |
154 | signed int type1 : 8; |
155 | /* True if the function is pointwise, so that it can be vectorized by |
156 | converting the return type and all argument types to vectors of the |
157 | same number of elements. E.g. we can vectorize an IFN_SQRT on |
158 | floats as an IFN_SQRT on vectors of N floats. |
159 | |
160 | This only needs 1 bit, but occupies the full 16 to ensure a nice |
161 | layout. */ |
162 | unsigned int vectorizable : 16; |
163 | }; |
164 | |
165 | extern const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1]; |
166 | |
167 | /* Return true if FN is mapped directly to an optab. */ |
168 | |
169 | inline bool |
170 | direct_internal_fn_p (internal_fn fn) |
171 | { |
172 | return direct_internal_fn_array[fn].type0 >= -1; |
173 | } |
174 | |
175 | /* Return true if FN is a direct internal function that can be vectorized by |
176 | converting the return type and all argument types to vectors of the same |
177 | number of elements. E.g. we can vectorize an IFN_SQRT on floats as an |
178 | IFN_SQRT on vectors of N floats. */ |
179 | |
180 | inline bool |
181 | vectorizable_internal_fn_p (internal_fn fn) |
182 | { |
183 | return direct_internal_fn_array[fn].vectorizable; |
184 | } |
185 | |
186 | /* Return optab information about internal function FN. Only meaningful |
187 | if direct_internal_fn_p (FN). */ |
188 | |
189 | inline const direct_internal_fn_info & |
190 | direct_internal_fn (internal_fn fn) |
191 | { |
192 | gcc_checking_assert (direct_internal_fn_p (fn)); |
193 | return direct_internal_fn_array[fn]; |
194 | } |
195 | |
196 | extern tree_pair direct_internal_fn_types (internal_fn, tree, tree *); |
197 | extern tree_pair direct_internal_fn_types (internal_fn, gcall *); |
198 | extern bool direct_internal_fn_supported_p (internal_fn, tree_pair, |
199 | optimization_type); |
200 | extern bool direct_internal_fn_supported_p (internal_fn, tree, |
201 | optimization_type); |
202 | extern bool direct_internal_fn_supported_p (gcall *, optimization_type); |
203 | |
204 | /* Return true if FN is supported for types TYPE0 and TYPE1 when the |
205 | optimization type is OPT_TYPE. The types are those associated with |
206 | the "type0" and "type1" fields of FN's direct_internal_fn_info |
207 | structure. */ |
208 | |
209 | inline bool |
210 | direct_internal_fn_supported_p (internal_fn fn, tree type0, tree type1, |
211 | optimization_type opt_type) |
212 | { |
213 | return direct_internal_fn_supported_p (fn, tree_pair (type0, type1), |
214 | opt_type); |
215 | } |
216 | |
217 | extern bool commutative_binary_fn_p (internal_fn); |
218 | extern bool commutative_ternary_fn_p (internal_fn); |
219 | extern int first_commutative_argument (internal_fn); |
220 | extern bool associative_binary_fn_p (internal_fn); |
221 | extern bool widening_fn_p (code_helper); |
222 | |
223 | extern bool set_edom_supported_p (void); |
224 | |
225 | extern internal_fn get_conditional_internal_fn (tree_code); |
226 | extern internal_fn get_conditional_internal_fn (internal_fn); |
227 | extern internal_fn get_len_internal_fn (internal_fn); |
228 | extern internal_fn get_conditional_len_internal_fn (tree_code); |
229 | extern tree_code conditional_internal_fn_code (internal_fn); |
230 | extern internal_fn get_unconditional_internal_fn (internal_fn); |
231 | extern bool can_interpret_as_conditional_op_p (gimple *, tree *, |
232 | tree_code *, tree (&)[3], |
233 | tree *, tree *, tree *); |
234 | |
235 | extern bool internal_load_fn_p (internal_fn); |
236 | extern bool internal_store_fn_p (internal_fn); |
237 | extern bool internal_gather_scatter_fn_p (internal_fn); |
238 | extern int internal_fn_mask_index (internal_fn); |
239 | extern int internal_fn_len_index (internal_fn); |
240 | extern int internal_fn_else_index (internal_fn); |
241 | extern int internal_fn_stored_value_index (internal_fn); |
242 | extern bool internal_gather_scatter_fn_supported_p (internal_fn, tree, |
243 | tree, tree, int); |
244 | extern bool internal_check_ptrs_fn_supported_p (internal_fn, tree, |
245 | poly_uint64, unsigned int); |
246 | #define VECT_PARTIAL_BIAS_UNSUPPORTED 127 |
247 | |
248 | extern signed char internal_len_load_store_bias (internal_fn ifn, |
249 | machine_mode); |
250 | |
251 | extern void expand_addsub_overflow (location_t, tree_code, tree, tree, tree, |
252 | bool, bool, bool, bool, tree *); |
253 | extern void expand_internal_call (gcall *); |
254 | extern void expand_internal_call (internal_fn, gcall *); |
255 | extern void expand_PHI (internal_fn, gcall *); |
256 | extern void expand_SHUFFLEVECTOR (internal_fn, gcall *); |
257 | extern void expand_SPACESHIP (internal_fn, gcall *); |
258 | extern void expand_TRAP (internal_fn, gcall *); |
259 | extern void expand_ASSUME (internal_fn, gcall *); |
260 | extern void expand_MASK_CALL (internal_fn, gcall *); |
261 | extern void expand_MULBITINT (internal_fn, gcall *); |
262 | extern void expand_DIVMODBITINT (internal_fn, gcall *); |
263 | extern void expand_FLOATTOBITINT (internal_fn, gcall *); |
264 | extern void expand_BITINTTOFLOAT (internal_fn, gcall *); |
265 | |
266 | extern bool vectorized_internal_fn_supported_p (internal_fn, tree); |
267 | |
268 | enum { |
269 | ATOMIC_OP_FETCH_CMP_0_EQ = 0, |
270 | ATOMIC_OP_FETCH_CMP_0_NE = 1, |
271 | ATOMIC_OP_FETCH_CMP_0_LT = 2, |
272 | ATOMIC_OP_FETCH_CMP_0_LE = 3, |
273 | ATOMIC_OP_FETCH_CMP_0_GT = 4, |
274 | ATOMIC_OP_FETCH_CMP_0_GE = 5 |
275 | }; |
276 | |
277 | #endif |
278 | |