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