1 | /* Gimple simplify definitions. |
2 | |
3 | Copyright (C) 2011-2023 Free Software Foundation, Inc. |
4 | Contributed by Richard Guenther <rguenther@suse.de> |
5 | |
6 | This file is part of GCC. |
7 | |
8 | GCC is free software; you can redistribute it and/or modify it under |
9 | the terms of the GNU General Public License as published by the Free |
10 | Software Foundation; either version 3, or (at your option) any later |
11 | version. |
12 | |
13 | GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
14 | WARRANTY; without even the implied warranty of MERCHANTABILITY or |
15 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
16 | for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with GCC; see the file COPYING3. If not see |
20 | <http://www.gnu.org/licenses/>. */ |
21 | |
22 | #ifndef GCC_GIMPLE_MATCH_H |
23 | #define GCC_GIMPLE_MATCH_H |
24 | |
25 | |
26 | /* Represents the condition under which an operation should happen, |
27 | and the value to use otherwise. The condition applies elementwise |
28 | (as for VEC_COND_EXPR) if the values are vectors. */ |
29 | class gimple_match_cond |
30 | { |
31 | public: |
32 | enum uncond { UNCOND }; |
33 | |
34 | /* Build an unconditional op. */ |
35 | gimple_match_cond (uncond) : cond (NULL_TREE), else_value (NULL_TREE), len |
36 | (NULL_TREE), bias (NULL_TREE) {} |
37 | gimple_match_cond (tree, tree); |
38 | gimple_match_cond (tree, tree, tree, tree); |
39 | |
40 | gimple_match_cond any_else () const; |
41 | |
42 | /* The condition under which the operation occurs, or NULL_TREE |
43 | if the operation is unconditional. */ |
44 | tree cond; |
45 | |
46 | /* The value to use when the condition is false. This is NULL_TREE if |
47 | the operation is unconditional or if the value doesn't matter. */ |
48 | tree else_value; |
49 | |
50 | /* The length and bias parameters to be applied to a vector operation, |
51 | so that the condition is forced to false when the element index is |
52 | >= LEN + BIAS. These are NULL_TREE if the operation isn't applied |
53 | to vectors, or if no such length limit is in use. */ |
54 | tree len; |
55 | tree bias; |
56 | }; |
57 | |
58 | inline |
59 | gimple_match_cond::gimple_match_cond (tree cond_in, tree else_value_in) |
60 | : cond (cond_in), else_value (else_value_in), len (NULL_TREE), |
61 | bias (NULL_TREE) |
62 | { |
63 | } |
64 | |
65 | inline |
66 | gimple_match_cond::gimple_match_cond (tree cond_in, tree else_value_in, |
67 | tree len_in, tree bias_in) |
68 | : cond (cond_in), else_value (else_value_in), len (len_in), bias (bias_in) |
69 | {} |
70 | |
71 | /* Return a gimple_match_cond with the same condition but with an |
72 | arbitrary ELSE_VALUE. */ |
73 | |
74 | inline gimple_match_cond |
75 | gimple_match_cond::any_else () const |
76 | { |
77 | return gimple_match_cond (cond, NULL_TREE); |
78 | } |
79 | |
80 | /* Represents an operation to be simplified, or the result of the |
81 | simplification. */ |
82 | class gimple_match_op |
83 | { |
84 | public: |
85 | gimple_match_op (); |
86 | gimple_match_op (const gimple_match_cond &, code_helper, tree, unsigned int); |
87 | gimple_match_op (const gimple_match_cond &, |
88 | code_helper, tree, tree); |
89 | gimple_match_op (const gimple_match_cond &, |
90 | code_helper, tree, tree, tree); |
91 | gimple_match_op (const gimple_match_cond &, |
92 | code_helper, tree, tree, tree, tree); |
93 | gimple_match_op (const gimple_match_cond &, |
94 | code_helper, tree, tree, tree, tree, tree); |
95 | gimple_match_op (const gimple_match_cond &, |
96 | code_helper, tree, tree, tree, tree, tree, tree); |
97 | gimple_match_op (const gimple_match_cond &, |
98 | code_helper, tree, tree, tree, tree, tree, tree, tree); |
99 | gimple_match_op (const gimple_match_cond &, |
100 | code_helper, tree, tree, tree, tree, tree, tree, tree, tree); |
101 | |
102 | void set_op (code_helper, tree, unsigned int); |
103 | void set_op (code_helper, tree, tree); |
104 | void set_op (code_helper, tree, tree, tree); |
105 | void set_op (code_helper, tree, tree, tree, tree); |
106 | void set_op (code_helper, tree, tree, tree, tree, bool); |
107 | void set_op (code_helper, tree, tree, tree, tree, tree); |
108 | void set_op (code_helper, tree, tree, tree, tree, tree, tree); |
109 | void set_op (code_helper, tree, tree, tree, tree, tree, tree, tree); |
110 | void set_op (code_helper, tree, tree, tree, tree, tree, tree, tree, tree); |
111 | void set_value (tree); |
112 | |
113 | tree op_or_null (unsigned int) const; |
114 | |
115 | bool resimplify (gimple_seq *, tree (*)(tree)); |
116 | |
117 | /* The maximum value of NUM_OPS. */ |
118 | static const unsigned int MAX_NUM_OPS = 7; |
119 | |
120 | /* The conditions under which the operation is performed, and the value to |
121 | use as a fallback. */ |
122 | gimple_match_cond cond; |
123 | |
124 | /* The operation being performed. */ |
125 | code_helper code; |
126 | |
127 | /* The type of the result. */ |
128 | tree type; |
129 | |
130 | /* For a BIT_FIELD_REF, whether the group of bits is stored in reverse order |
131 | from the target order. */ |
132 | bool reverse; |
133 | |
134 | /* The number of operands to CODE. */ |
135 | unsigned int num_ops; |
136 | |
137 | /* The operands to CODE. Only the first NUM_OPS entries are meaningful. */ |
138 | tree ops[MAX_NUM_OPS]; |
139 | }; |
140 | |
141 | inline |
142 | gimple_match_op::gimple_match_op () |
143 | : cond (gimple_match_cond::UNCOND), type (NULL_TREE), reverse (false), |
144 | num_ops (0) |
145 | { |
146 | } |
147 | |
148 | /* Constructor that takes the condition, code, type and number of |
149 | operands, but leaves the caller to fill in the operands. */ |
150 | |
151 | inline |
152 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
153 | code_helper code_in, tree type_in, |
154 | unsigned int num_ops_in) |
155 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
156 | num_ops (num_ops_in) |
157 | { |
158 | } |
159 | |
160 | /* Constructors for various numbers of operands. */ |
161 | |
162 | inline |
163 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
164 | code_helper code_in, tree type_in, |
165 | tree op0) |
166 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
167 | num_ops (1) |
168 | { |
169 | ops[0] = op0; |
170 | } |
171 | |
172 | inline |
173 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
174 | code_helper code_in, tree type_in, |
175 | tree op0, tree op1) |
176 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
177 | num_ops (2) |
178 | { |
179 | ops[0] = op0; |
180 | ops[1] = op1; |
181 | } |
182 | |
183 | inline |
184 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
185 | code_helper code_in, tree type_in, |
186 | tree op0, tree op1, tree op2) |
187 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
188 | num_ops (3) |
189 | { |
190 | ops[0] = op0; |
191 | ops[1] = op1; |
192 | ops[2] = op2; |
193 | } |
194 | |
195 | inline |
196 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
197 | code_helper code_in, tree type_in, |
198 | tree op0, tree op1, tree op2, tree op3) |
199 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
200 | num_ops (4) |
201 | { |
202 | ops[0] = op0; |
203 | ops[1] = op1; |
204 | ops[2] = op2; |
205 | ops[3] = op3; |
206 | } |
207 | |
208 | inline |
209 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
210 | code_helper code_in, tree type_in, |
211 | tree op0, tree op1, tree op2, tree op3, |
212 | tree op4) |
213 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
214 | num_ops (5) |
215 | { |
216 | ops[0] = op0; |
217 | ops[1] = op1; |
218 | ops[2] = op2; |
219 | ops[3] = op3; |
220 | ops[4] = op4; |
221 | } |
222 | |
223 | inline |
224 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
225 | code_helper code_in, tree type_in, |
226 | tree op0, tree op1, tree op2, tree op3, |
227 | tree op4, tree op5) |
228 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
229 | num_ops (6) |
230 | { |
231 | ops[0] = op0; |
232 | ops[1] = op1; |
233 | ops[2] = op2; |
234 | ops[3] = op3; |
235 | ops[4] = op4; |
236 | ops[5] = op5; |
237 | } |
238 | |
239 | inline |
240 | gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in, |
241 | code_helper code_in, tree type_in, |
242 | tree op0, tree op1, tree op2, tree op3, |
243 | tree op4, tree op5, tree op6) |
244 | : cond (cond_in), code (code_in), type (type_in), reverse (false), |
245 | num_ops (7) |
246 | { |
247 | ops[0] = op0; |
248 | ops[1] = op1; |
249 | ops[2] = op2; |
250 | ops[3] = op3; |
251 | ops[4] = op4; |
252 | ops[5] = op5; |
253 | ops[6] = op6; |
254 | } |
255 | |
256 | /* Change the operation performed to CODE_IN, the type of the result to |
257 | TYPE_IN, and the number of operands to NUM_OPS_IN. The caller needs |
258 | to set the operands itself. */ |
259 | |
260 | inline void |
261 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
262 | unsigned int num_ops_in) |
263 | { |
264 | code = code_in; |
265 | type = type_in; |
266 | num_ops = num_ops_in; |
267 | } |
268 | |
269 | /* Functions for changing the operation performed, for various numbers |
270 | of operands. */ |
271 | |
272 | inline void |
273 | gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0) |
274 | { |
275 | code = code_in; |
276 | type = type_in; |
277 | num_ops = 1; |
278 | ops[0] = op0; |
279 | } |
280 | |
281 | inline void |
282 | gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0, tree op1) |
283 | { |
284 | code = code_in; |
285 | type = type_in; |
286 | num_ops = 2; |
287 | ops[0] = op0; |
288 | ops[1] = op1; |
289 | } |
290 | |
291 | inline void |
292 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
293 | tree op0, tree op1, tree op2) |
294 | { |
295 | code = code_in; |
296 | type = type_in; |
297 | num_ops = 3; |
298 | ops[0] = op0; |
299 | ops[1] = op1; |
300 | ops[2] = op2; |
301 | } |
302 | |
303 | inline void |
304 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
305 | tree op0, tree op1, tree op2, bool reverse_in) |
306 | { |
307 | code = code_in; |
308 | type = type_in; |
309 | reverse = reverse_in; |
310 | num_ops = 3; |
311 | ops[0] = op0; |
312 | ops[1] = op1; |
313 | ops[2] = op2; |
314 | } |
315 | |
316 | inline void |
317 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
318 | tree op0, tree op1, tree op2, tree op3) |
319 | { |
320 | code = code_in; |
321 | type = type_in; |
322 | num_ops = 4; |
323 | ops[0] = op0; |
324 | ops[1] = op1; |
325 | ops[2] = op2; |
326 | ops[3] = op3; |
327 | } |
328 | |
329 | inline void |
330 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
331 | tree op0, tree op1, tree op2, tree op3, tree op4) |
332 | { |
333 | code = code_in; |
334 | type = type_in; |
335 | num_ops = 5; |
336 | ops[0] = op0; |
337 | ops[1] = op1; |
338 | ops[2] = op2; |
339 | ops[3] = op3; |
340 | ops[4] = op4; |
341 | } |
342 | |
343 | inline void |
344 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
345 | tree op0, tree op1, tree op2, tree op3, tree op4, |
346 | tree op5) |
347 | { |
348 | code = code_in; |
349 | type = type_in; |
350 | num_ops = 6; |
351 | ops[0] = op0; |
352 | ops[1] = op1; |
353 | ops[2] = op2; |
354 | ops[3] = op3; |
355 | ops[4] = op4; |
356 | ops[5] = op5; |
357 | } |
358 | |
359 | inline void |
360 | gimple_match_op::set_op (code_helper code_in, tree type_in, |
361 | tree op0, tree op1, tree op2, tree op3, tree op4, |
362 | tree op5, tree op6) |
363 | { |
364 | code = code_in; |
365 | type = type_in; |
366 | num_ops = 7; |
367 | ops[0] = op0; |
368 | ops[1] = op1; |
369 | ops[2] = op2; |
370 | ops[3] = op3; |
371 | ops[4] = op4; |
372 | ops[5] = op5; |
373 | ops[6] = op6; |
374 | } |
375 | |
376 | /* Set the "operation" to be the single value VALUE, such as a constant |
377 | or SSA_NAME. */ |
378 | |
379 | inline void |
380 | gimple_match_op::set_value (tree value) |
381 | { |
382 | set_op (TREE_CODE (value), TREE_TYPE (value), op0: value); |
383 | } |
384 | |
385 | /* Return the value of operand I, or null if there aren't that many |
386 | operands. */ |
387 | |
388 | inline tree |
389 | gimple_match_op::op_or_null (unsigned int i) const |
390 | { |
391 | return i < num_ops ? ops[i] : NULL_TREE; |
392 | } |
393 | |
394 | /* Return whether OP is a non-expression result and a gimple value. */ |
395 | |
396 | inline bool |
397 | gimple_simplified_result_is_gimple_val (const gimple_match_op *op) |
398 | { |
399 | return (op->code.is_tree_code () |
400 | && (TREE_CODE_LENGTH ((tree_code) op->code) == 0 |
401 | || ((tree_code) op->code) == ADDR_EXPR) |
402 | && is_gimple_val (op->ops[0])); |
403 | } |
404 | |
405 | extern tree (*mprts_hook) (gimple_match_op *); |
406 | |
407 | bool (gimple *, gimple_match_op *); |
408 | bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *, |
409 | tree (*)(tree), tree (*)(tree)); |
410 | tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *, |
411 | tree res = NULL_TREE); |
412 | void maybe_build_generic_op (gimple_match_op *); |
413 | |
414 | bool commutative_binary_op_p (code_helper, tree); |
415 | bool commutative_ternary_op_p (code_helper, tree); |
416 | int first_commutative_argument (code_helper, tree); |
417 | bool associative_binary_op_p (code_helper, tree); |
418 | code_helper canonicalize_code (code_helper, tree); |
419 | |
420 | #ifdef GCC_OPTABS_TREE_H |
421 | bool directly_supported_p (code_helper, tree, optab_subtype = optab_default); |
422 | #endif |
423 | |
424 | internal_fn get_conditional_internal_fn (code_helper, tree); |
425 | |
426 | #endif /* GCC_GIMPLE_MATCH_H */ |
427 | |