Line data Source code
1 : /* Gimple simplify definitions.
2 :
3 : Copyright (C) 2011-2026 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 1357636503 : gimple_match_cond (uncond) : cond (NULL_TREE), else_value (NULL_TREE), len
36 1355555132 : (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 7532268 : 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 13143 : 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 7532268 : gimple_match_cond::any_else () const
76 : {
77 7532268 : 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 : bool operands_occurs_in_abnormal_phi() const;
141 : };
142 :
143 : inline
144 1355555132 : gimple_match_op::gimple_match_op ()
145 1355555132 : : cond (gimple_match_cond::UNCOND), type (NULL_TREE), reverse (false),
146 1355555132 : num_ops (0)
147 : {
148 : }
149 :
150 : /* Constructor that takes the condition, code, type and number of
151 : operands, but leaves the caller to fill in the operands. */
152 :
153 : inline
154 7413451 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
155 : code_helper code_in, tree type_in,
156 7413451 : unsigned int num_ops_in)
157 7409424 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
158 7413098 : num_ops (num_ops_in)
159 : {
160 : }
161 :
162 : /* Constructors for various numbers of operands. */
163 :
164 : inline
165 13611012 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
166 : code_helper code_in, tree type_in,
167 13611012 : tree op0)
168 13611012 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
169 13611012 : num_ops (1)
170 : {
171 13611012 : ops[0] = op0;
172 : }
173 :
174 : inline
175 5756884 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
176 : code_helper code_in, tree type_in,
177 5756884 : tree op0, tree op1)
178 5756884 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
179 5756884 : num_ops (2)
180 : {
181 5756884 : ops[0] = op0;
182 5756884 : ops[1] = op1;
183 : }
184 :
185 : inline
186 1032314 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
187 : code_helper code_in, tree type_in,
188 1032314 : tree op0, tree op1, tree op2)
189 1032314 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
190 1032314 : num_ops (3)
191 : {
192 1032314 : ops[0] = op0;
193 1032314 : ops[1] = op1;
194 1032314 : ops[2] = op2;
195 : }
196 :
197 : inline
198 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
199 : code_helper code_in, tree type_in,
200 : tree op0, tree op1, tree op2, tree op3)
201 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
202 : num_ops (4)
203 : {
204 : ops[0] = op0;
205 : ops[1] = op1;
206 : ops[2] = op2;
207 : ops[3] = op3;
208 : }
209 :
210 : inline
211 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
212 : code_helper code_in, tree type_in,
213 : tree op0, tree op1, tree op2, tree op3,
214 : tree op4)
215 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
216 : num_ops (5)
217 : {
218 : ops[0] = op0;
219 : ops[1] = op1;
220 : ops[2] = op2;
221 : ops[3] = op3;
222 : ops[4] = op4;
223 : }
224 :
225 : inline
226 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
227 : code_helper code_in, tree type_in,
228 : tree op0, tree op1, tree op2, tree op3,
229 : tree op4, tree op5)
230 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
231 : num_ops (6)
232 : {
233 : ops[0] = op0;
234 : ops[1] = op1;
235 : ops[2] = op2;
236 : ops[3] = op3;
237 : ops[4] = op4;
238 : ops[5] = op5;
239 : }
240 :
241 : inline
242 : gimple_match_op::gimple_match_op (const gimple_match_cond &cond_in,
243 : code_helper code_in, tree type_in,
244 : tree op0, tree op1, tree op2, tree op3,
245 : tree op4, tree op5, tree op6)
246 : : cond (cond_in), code (code_in), type (type_in), reverse (false),
247 : num_ops (7)
248 : {
249 : ops[0] = op0;
250 : ops[1] = op1;
251 : ops[2] = op2;
252 : ops[3] = op3;
253 : ops[4] = op4;
254 : ops[5] = op5;
255 : ops[6] = op6;
256 : }
257 :
258 : /* Change the operation performed to CODE_IN, the type of the result to
259 : TYPE_IN, and the number of operands to NUM_OPS_IN. The caller needs
260 : to set the operands itself. */
261 :
262 : inline void
263 31723856 : gimple_match_op::set_op (code_helper code_in, tree type_in,
264 : unsigned int num_ops_in)
265 : {
266 31723856 : code = code_in;
267 31723856 : type = type_in;
268 30682890 : num_ops = num_ops_in;
269 : }
270 :
271 : /* Functions for changing the operation performed, for various numbers
272 : of operands. */
273 :
274 : inline void
275 199606463 : gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0)
276 : {
277 199606463 : code = code_in;
278 199606463 : type = type_in;
279 199606463 : num_ops = 1;
280 165705936 : ops[0] = op0;
281 : }
282 :
283 : inline void
284 489313915 : gimple_match_op::set_op (code_helper code_in, tree type_in, tree op0, tree op1)
285 : {
286 489313915 : code = code_in;
287 489313915 : type = type_in;
288 489313915 : num_ops = 2;
289 489313915 : ops[0] = op0;
290 489313915 : ops[1] = op1;
291 : }
292 :
293 : inline void
294 1302393 : gimple_match_op::set_op (code_helper code_in, tree type_in,
295 : tree op0, tree op1, tree op2)
296 : {
297 1302393 : code = code_in;
298 1302393 : type = type_in;
299 1302393 : num_ops = 3;
300 1302393 : ops[0] = op0;
301 1302393 : ops[1] = op1;
302 1302393 : ops[2] = op2;
303 : }
304 :
305 : inline void
306 905737 : gimple_match_op::set_op (code_helper code_in, tree type_in,
307 : tree op0, tree op1, tree op2, bool reverse_in)
308 : {
309 905737 : code = code_in;
310 905737 : type = type_in;
311 905737 : reverse = reverse_in;
312 905737 : num_ops = 3;
313 905737 : ops[0] = op0;
314 905737 : ops[1] = op1;
315 905737 : ops[2] = op2;
316 : }
317 :
318 : inline void
319 : gimple_match_op::set_op (code_helper code_in, tree type_in,
320 : tree op0, tree op1, tree op2, tree op3)
321 : {
322 : code = code_in;
323 : type = type_in;
324 : num_ops = 4;
325 : ops[0] = op0;
326 : ops[1] = op1;
327 : ops[2] = op2;
328 : ops[3] = op3;
329 : }
330 :
331 : inline void
332 0 : gimple_match_op::set_op (code_helper code_in, tree type_in,
333 : tree op0, tree op1, tree op2, tree op3, tree op4)
334 : {
335 0 : code = code_in;
336 0 : type = type_in;
337 0 : num_ops = 5;
338 0 : ops[0] = op0;
339 0 : ops[1] = op1;
340 0 : ops[2] = op2;
341 0 : ops[3] = op3;
342 0 : ops[4] = op4;
343 : }
344 :
345 : inline void
346 : gimple_match_op::set_op (code_helper code_in, tree type_in,
347 : tree op0, tree op1, tree op2, tree op3, tree op4,
348 : tree op5)
349 : {
350 : code = code_in;
351 : type = type_in;
352 : num_ops = 6;
353 : ops[0] = op0;
354 : ops[1] = op1;
355 : ops[2] = op2;
356 : ops[3] = op3;
357 : ops[4] = op4;
358 : ops[5] = op5;
359 : }
360 :
361 : inline void
362 : gimple_match_op::set_op (code_helper code_in, tree type_in,
363 : tree op0, tree op1, tree op2, tree op3, tree op4,
364 : tree op5, tree op6)
365 : {
366 : code = code_in;
367 : type = type_in;
368 : num_ops = 7;
369 : ops[0] = op0;
370 : ops[1] = op1;
371 : ops[2] = op2;
372 : ops[3] = op3;
373 : ops[4] = op4;
374 : ops[5] = op5;
375 : ops[6] = op6;
376 : }
377 :
378 : /* Set the "operation" to be the single value VALUE, such as a constant
379 : or SSA_NAME. */
380 :
381 : inline void
382 66421202 : gimple_match_op::set_value (tree value)
383 : {
384 66421202 : set_op (TREE_CODE (value), TREE_TYPE (value), value);
385 66421202 : }
386 :
387 : /* Return the value of operand I, or null if there aren't that many
388 : operands. */
389 :
390 : inline tree
391 8758393 : gimple_match_op::op_or_null (unsigned int i) const
392 : {
393 2905957 : return i < num_ops ? ops[i] : NULL_TREE;
394 : }
395 :
396 : /* Return whether OP is a non-expression result and a gimple value. */
397 :
398 : inline bool
399 74567074 : gimple_simplified_result_is_gimple_val (const gimple_match_op *op)
400 : {
401 74567074 : return (op->code.is_tree_code ()
402 73978986 : && (TREE_CODE_LENGTH ((tree_code) op->code) == 0
403 29287873 : || ((tree_code) op->code) == ADDR_EXPR)
404 120346600 : && is_gimple_val (op->ops[0]));
405 : }
406 :
407 : extern tree (*mprts_hook) (gimple_match_op *);
408 :
409 : bool gimple_extract_op (gimple *, gimple_match_op *);
410 : bool gimple_simplify (gimple *, gimple_match_op *, gimple_seq *,
411 : tree (*)(tree), tree (*)(tree));
412 : tree maybe_push_res_to_seq (gimple_match_op *, gimple_seq *,
413 : tree res = NULL_TREE);
414 : void maybe_build_generic_op (gimple_match_op *);
415 :
416 : bool commutative_binary_op_p (code_helper, tree);
417 : bool commutative_ternary_op_p (code_helper, tree);
418 : int first_commutative_argument (code_helper, tree);
419 : bool associative_binary_op_p (code_helper, tree);
420 : code_helper canonicalize_code (code_helper, tree);
421 :
422 : #ifdef GCC_OPTABS_TREE_H
423 : bool directly_supported_p (code_helper, tree, optab_subtype = optab_default);
424 : bool directly_supported_p (code_helper, tree, tree,
425 : optab_subtype = optab_default);
426 : #endif
427 :
428 : internal_fn get_conditional_internal_fn (code_helper, tree);
429 :
430 : #endif /* GCC_GIMPLE_MATCH_H */
|