Branch data Line data Source code
1 : : /* Helpers for the autogenerated gimple-match.cc file.
2 : : Copyright (C) 2023-2025 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 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "backend.h"
24 : : #include "target.h"
25 : : #include "rtl.h"
26 : : #include "tree.h"
27 : : #include "gimple.h"
28 : : #include "ssa.h"
29 : : #include "cgraph.h"
30 : : #include "vec-perm-indices.h"
31 : : #include "fold-const.h"
32 : : #include "fold-const-call.h"
33 : : #include "stor-layout.h"
34 : : #include "gimple-iterator.h"
35 : : #include "gimple-fold.h"
36 : : #include "calls.h"
37 : : #include "tree-dfa.h"
38 : : #include "builtins.h"
39 : : #include "gimple-match.h"
40 : : #include "tree-pass.h"
41 : : #include "internal-fn.h"
42 : : #include "case-cfn-macros.h"
43 : : #include "gimplify.h"
44 : : #include "optabs-tree.h"
45 : : #include "tree-eh.h"
46 : : #include "dbgcnt.h"
47 : : #include "tm.h"
48 : : #include "gimple-range.h"
49 : : #include "langhooks.h"
50 : :
51 : : tree (*mprts_hook) (gimple_match_op *);
52 : :
53 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
54 : : code_helper, tree, tree);
55 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
56 : : code_helper, tree, tree, tree);
57 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
58 : : code_helper, tree, tree, tree, tree);
59 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
60 : : code_helper, tree, tree, tree, tree, tree);
61 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
62 : : code_helper, tree, tree, tree, tree, tree, tree);
63 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
64 : : code_helper, tree, tree, tree, tree, tree, tree,
65 : : tree);
66 : : extern bool gimple_simplify (gimple_match_op *, gimple_seq *, tree (*)(tree),
67 : : code_helper, tree, tree, tree, tree, tree, tree,
68 : : tree, tree);
69 : :
70 : : /* Functions that are needed by gimple-match but that are exported and used in
71 : : other places in the compiler. */
72 : :
73 : : tree gimple_simplify (enum tree_code, tree, tree, gimple_seq *,
74 : : tree (*)(tree));
75 : : tree gimple_simplify (enum tree_code, tree, tree, tree, gimple_seq *,
76 : : tree (*)(tree));
77 : : tree gimple_simplify (enum tree_code, tree, tree, tree, tree, gimple_seq *,
78 : : tree (*)(tree));
79 : : tree gimple_simplify (combined_fn, tree, tree, gimple_seq *,
80 : : tree (*)(tree));
81 : : tree gimple_simplify (combined_fn, tree, tree, tree, gimple_seq *,
82 : : tree (*)(tree));
83 : : tree gimple_simplify (combined_fn, tree, tree, tree, tree, gimple_seq *,
84 : : tree (*)(tree));
85 : :
86 : : tree do_valueize (tree, tree (*)(tree), bool &);
87 : : tree do_valueize (tree (*)(tree), tree);
88 : :
89 : : /* Forward declarations of the private auto-generated matchers.
90 : : They expect valueized operands in canonical order and do not
91 : : perform simplification of all-constant operands. */
92 : :
93 : : static bool gimple_resimplify1 (gimple_seq *, gimple_match_op *, tree (*)(tree));
94 : : static bool gimple_resimplify2 (gimple_seq *, gimple_match_op *, tree (*)(tree));
95 : : static bool gimple_resimplify3 (gimple_seq *, gimple_match_op *, tree (*)(tree));
96 : : static bool gimple_resimplify4 (gimple_seq *, gimple_match_op *, tree (*)(tree));
97 : : static bool gimple_resimplify5 (gimple_seq *, gimple_match_op *, tree (*)(tree));
98 : : static bool gimple_resimplify6 (gimple_seq *, gimple_match_op *, tree (*)(tree));
99 : : static bool gimple_resimplify7 (gimple_seq *, gimple_match_op *, tree (*)(tree));
100 : :
101 : : /* Match and simplify the toplevel valueized operation THIS.
102 : : Replaces THIS with a simplified and/or canonicalized result and
103 : : returns whether any change was made. */
104 : :
105 : : bool
106 : 661564082 : gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
107 : : {
108 : 661564082 : switch (num_ops)
109 : : {
110 : 150369867 : case 1:
111 : 150369867 : return gimple_resimplify1 (seq, this, valueize);
112 : 503850823 : case 2:
113 : 503850823 : return gimple_resimplify2 (seq, this, valueize);
114 : 6373750 : case 3:
115 : 6373750 : return gimple_resimplify3 (seq, this, valueize);
116 : 249771 : case 4:
117 : 249771 : return gimple_resimplify4 (seq, this, valueize);
118 : 25656 : case 5:
119 : 25656 : return gimple_resimplify5 (seq, this, valueize);
120 : 611848 : case 6:
121 : 611848 : return gimple_resimplify6 (seq, this, valueize);
122 : 82367 : case 7:
123 : 82367 : return gimple_resimplify7 (seq, this, valueize);
124 : 0 : default:
125 : 0 : gcc_unreachable ();
126 : : }
127 : : }
128 : :
129 : : /* Returns true if any of the operands of THIS occurs
130 : : in abnormal phis. */
131 : : bool
132 : 562283 : gimple_match_op::operands_occurs_in_abnormal_phi() const
133 : : {
134 : 1558301 : for (unsigned int i = 0; i < num_ops; i++)
135 : : {
136 : 996018 : if (TREE_CODE (ops[i]) == SSA_NAME
137 : 996018 : && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
138 : : return true;
139 : : }
140 : : return false;
141 : : }
142 : :
143 : : /* Return whether T is a constant that we'll dispatch to fold to
144 : : evaluate fully constant expressions. */
145 : :
146 : : static inline bool
147 : 716221540 : constant_for_folding (tree t)
148 : : {
149 : 716221540 : return (CONSTANT_CLASS_P (t)
150 : : /* The following is only interesting to string builtins. */
151 : 716221540 : || (TREE_CODE (t) == ADDR_EXPR
152 : 13368860 : && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST));
153 : : }
154 : :
155 : : /* Try to convert conditional operation ORIG_OP into an IFN_COND_*
156 : : operation. Return true on success, storing the new operation in NEW_OP. */
157 : :
158 : : static bool
159 : 8923 : convert_conditional_op (gimple_match_op *orig_op,
160 : : gimple_match_op *new_op)
161 : : {
162 : 8923 : internal_fn ifn;
163 : 8923 : if (orig_op->code.is_tree_code ())
164 : 8493 : ifn = get_conditional_internal_fn ((tree_code) orig_op->code);
165 : : else
166 : : {
167 : 430 : auto cfn = combined_fn (orig_op->code);
168 : 430 : if (!internal_fn_p (cfn))
169 : : return false;
170 : 430 : ifn = get_conditional_internal_fn (as_internal_fn (cfn));
171 : : }
172 : 8923 : if (ifn == IFN_LAST)
173 : : return false;
174 : 7979 : unsigned int num_ops = orig_op->num_ops;
175 : 7979 : unsigned int num_cond_ops = 2;
176 : 7979 : if (orig_op->cond.len)
177 : : {
178 : : /* Add the length and bias parameters. */
179 : 0 : ifn = get_len_internal_fn (ifn);
180 : 0 : num_cond_ops = 4;
181 : : }
182 : 7979 : new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + num_cond_ops);
183 : 7979 : new_op->ops[0] = orig_op->cond.cond;
184 : 24364 : for (unsigned int i = 0; i < num_ops; ++i)
185 : 16385 : new_op->ops[i + 1] = orig_op->ops[i];
186 : 7979 : tree else_value = orig_op->cond.else_value;
187 : 7979 : if (!else_value)
188 : 6 : else_value = targetm.preferred_else_value (ifn, orig_op->type,
189 : 6 : num_ops, orig_op->ops);
190 : 7979 : new_op->ops[num_ops + 1] = else_value;
191 : 7979 : if (orig_op->cond.len)
192 : : {
193 : 0 : new_op->ops[num_ops + 2] = orig_op->cond.len;
194 : 0 : new_op->ops[num_ops + 3] = orig_op->cond.bias;
195 : : }
196 : : return true;
197 : : }
198 : : /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
199 : : VALUEIZED to true if valueization changed OP. */
200 : :
201 : : inline tree
202 : 1149336387 : do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
203 : : {
204 : 1149336387 : if (valueize && TREE_CODE (op) == SSA_NAME)
205 : : {
206 : 724818256 : tree tem = valueize (op);
207 : 724818256 : if (tem && tem != op)
208 : : {
209 : 50745451 : op = tem;
210 : 50745451 : valueized = true;
211 : : }
212 : : }
213 : 1149336387 : return op;
214 : : }
215 : :
216 : : /* If in GIMPLE the operation described by RES_OP should be single-rhs,
217 : : build a GENERIC tree for that expression and update RES_OP accordingly. */
218 : :
219 : : void
220 : 2729144 : maybe_build_generic_op (gimple_match_op *res_op)
221 : : {
222 : 2729144 : tree_code code = (tree_code) res_op->code;
223 : 2729144 : tree val;
224 : 2729144 : switch (code)
225 : : {
226 : 8983 : case REALPART_EXPR:
227 : 8983 : case IMAGPART_EXPR:
228 : 8983 : case VIEW_CONVERT_EXPR:
229 : 8983 : val = build1 (code, res_op->type, res_op->ops[0]);
230 : 8983 : res_op->set_value (val);
231 : 8983 : break;
232 : 77958 : case BIT_FIELD_REF:
233 : 77958 : val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
234 : : res_op->ops[2]);
235 : 77958 : REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
236 : 77958 : res_op->set_value (val);
237 : 77958 : break;
238 : 2729144 : default:;
239 : : }
240 : 2729144 : }
241 : :
242 : : /* Try to build RES_OP, which is known to be a call to FN. Return null
243 : : if the target doesn't support the function. */
244 : :
245 : : static gcall *
246 : 8836 : build_call_internal (internal_fn fn, gimple_match_op *res_op)
247 : : {
248 : 8836 : if (direct_internal_fn_p (fn))
249 : : {
250 : 8804 : tree_pair types = direct_internal_fn_types (fn, res_op->type,
251 : 8804 : res_op->ops);
252 : 8804 : if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
253 : : {
254 : 76 : switch (fn)
255 : : {
256 : 2 : case IFN_CLZ:
257 : 2 : case IFN_CTZ:
258 : 2 : case IFN_CLRSB:
259 : 2 : case IFN_FFS:
260 : 2 : case IFN_POPCOUNT:
261 : 2 : case IFN_PARITY:
262 : : /* For these 6 builtins large/huge _BitInt operand is ok
263 : : before bitint lowering pass. */
264 : 2 : if (res_op->num_ops >= 1
265 : 2 : && TREE_CODE (TREE_TYPE (res_op->ops[0])) == BITINT_TYPE
266 : 2 : && (TYPE_PRECISION (TREE_TYPE (res_op->ops[0]))
267 : 4 : > MAX_FIXED_MODE_SIZE)
268 : 2 : && cfun
269 : 4 : && (cfun->curr_properties & PROP_gimple_lbitint) == 0)
270 : : break;
271 : 74 : return NULL;
272 : :
273 : : default:
274 : : return NULL;
275 : : }
276 : : }
277 : : }
278 : 35474 : return gimple_build_call_internal (fn, res_op->num_ops,
279 : : res_op->op_or_null (0),
280 : : res_op->op_or_null (1),
281 : : res_op->op_or_null (2),
282 : : res_op->op_or_null (3),
283 : : res_op->op_or_null (4),
284 : : res_op->op_or_null (5),
285 : 8762 : res_op->op_or_null (6));
286 : : }
287 : :
288 : : /* RES_OP is the result of a simplification. If it is conditional,
289 : : try to replace it with the equivalent UNCOND form, such as an
290 : : IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the
291 : : result of the replacement if appropriate, adding any new statements to
292 : : SEQ and using VALUEIZE as the valueization function. Return true if
293 : : this resimplification occurred and resulted in at least one change. */
294 : :
295 : : static bool
296 : 619992263 : maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
297 : : tree (*valueize) (tree))
298 : : {
299 : 619992263 : if (!res_op->cond.cond)
300 : : return false;
301 : :
302 : 10923 : if (!res_op->cond.else_value
303 : 10923 : && res_op->code.is_tree_code ())
304 : : {
305 : : /* The "else" value doesn't matter. If the "then" value is a
306 : : gimple value, just use it unconditionally. This isn't a
307 : : simplification in itself, since there was no operation to
308 : : build in the first place. */
309 : 1126 : if (gimple_simplified_result_is_gimple_val (res_op))
310 : : {
311 : 1114 : res_op->cond.cond = NULL_TREE;
312 : 1114 : return false;
313 : : }
314 : :
315 : : /* Likewise if the operation would not trap. */
316 : 12 : bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
317 : 12 : && TYPE_OVERFLOW_TRAPS (res_op->type));
318 : 12 : tree_code op_code = (tree_code) res_op->code;
319 : 12 : bool op_could_trap;
320 : :
321 : : /* COND_EXPR will trap if, and only if, the condition
322 : : traps and hence we have to check this. For all other operations, we
323 : : don't need to consider the operands. */
324 : 12 : if (op_code == COND_EXPR)
325 : 0 : op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
326 : : else
327 : 24 : op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
328 : 12 : FLOAT_TYPE_P (res_op->type),
329 : : honor_trapv,
330 : : res_op->op_or_null (1));
331 : :
332 : 12 : if (!op_could_trap)
333 : : {
334 : 6 : res_op->cond.cond = NULL_TREE;
335 : 6 : return false;
336 : : }
337 : : }
338 : :
339 : : /* If the "then" value is a gimple value and the "else" value matters,
340 : : create a (VEC_)COND_EXPR between them, then see if it can be further
341 : : simplified. */
342 : 9803 : gimple_match_op new_op;
343 : 9803 : if (res_op->cond.else_value
344 : 9803 : && gimple_simplified_result_is_gimple_val (res_op))
345 : : {
346 : 880 : if (VECTOR_TYPE_P (res_op->type))
347 : : {
348 : 880 : tree len = res_op->cond.len;
349 : 880 : if (!len)
350 : 880 : new_op.set_op (VEC_COND_EXPR, res_op->type,
351 : : res_op->cond.cond, res_op->ops[0],
352 : : res_op->cond.else_value);
353 : : else
354 : 0 : new_op.set_op (IFN_VCOND_MASK_LEN, res_op->type,
355 : : res_op->cond.cond, res_op->ops[0],
356 : : res_op->cond.else_value,
357 : : res_op->cond.len, res_op->cond.bias);
358 : : }
359 : : else
360 : 0 : new_op.set_op (COND_EXPR, res_op->type,
361 : : res_op->cond.cond, res_op->ops[0],
362 : : res_op->cond.else_value);
363 : 880 : *res_op = new_op;
364 : 880 : return gimple_resimplify3 (seq, res_op, valueize);
365 : : }
366 : :
367 : : /* Otherwise try rewriting the operation as an IFN_COND_* call.
368 : : Again, this isn't a simplification in itself, since it's what
369 : : RES_OP already described. */
370 : 8923 : if (convert_conditional_op (res_op, &new_op))
371 : 7979 : *res_op = new_op;
372 : :
373 : : return false;
374 : : }
375 : :
376 : : /* If RES_OP is a call to a conditional internal function, try simplifying
377 : : the associated unconditional operation and using the result to build
378 : : a new conditional operation. For example, if RES_OP is:
379 : :
380 : : IFN_COND_ADD (COND, A, B, ELSE)
381 : :
382 : : try simplifying (plus A B) and using the result to build a replacement
383 : : for the whole IFN_COND_ADD.
384 : :
385 : : Return true if this approach led to a simplification, otherwise leave
386 : : RES_OP unchanged (and so suitable for other simplifications). When
387 : : returning true, add any new statements to SEQ and use VALUEIZE as the
388 : : valueization function.
389 : :
390 : : RES_OP is known to be a call to IFN. */
391 : :
392 : : static bool
393 : 2470668 : try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
394 : : gimple_seq *seq, tree (*valueize) (tree))
395 : : {
396 : 2470668 : code_helper op;
397 : 2470668 : tree_code code = conditional_internal_fn_code (ifn);
398 : 2470668 : int len_index = internal_fn_len_index (ifn);
399 : 2470668 : if (code != ERROR_MARK)
400 : 8895 : op = code;
401 : : else
402 : : {
403 : 2461773 : ifn = get_unconditional_internal_fn (ifn);
404 : 2461773 : if (ifn == IFN_LAST)
405 : : return false;
406 : 430 : op = as_combined_fn (ifn);
407 : : }
408 : :
409 : 9325 : unsigned int num_ops = res_op->num_ops;
410 : : /* num_cond_ops = 2 for COND_ADD (MASK and ELSE)
411 : : wheras num_cond_ops = 4 for COND_LEN_ADD (MASK, ELSE, LEN and BIAS). */
412 : 9325 : unsigned int num_cond_ops = len_index < 0 ? 2 : 4;
413 : 9325 : tree else_value
414 : 9325 : = len_index < 0 ? res_op->ops[num_ops - 1] : res_op->ops[num_ops - 3];
415 : 9325 : tree len = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 2];
416 : 0 : tree bias = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 1];
417 : 9325 : gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
418 : 9325 : else_value, len, bias),
419 : 9325 : op, res_op->type, num_ops - num_cond_ops);
420 : :
421 : 9325 : memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
422 : 9325 : switch (num_ops - num_cond_ops)
423 : : {
424 : 0 : case 1:
425 : 0 : if (!gimple_resimplify1 (seq, &cond_op, valueize))
426 : : return false;
427 : : break;
428 : 8895 : case 2:
429 : 8895 : if (!gimple_resimplify2 (seq, &cond_op, valueize))
430 : : return false;
431 : : break;
432 : 430 : case 3:
433 : 430 : if (!gimple_resimplify3 (seq, &cond_op, valueize))
434 : : return false;
435 : : break;
436 : 0 : default:
437 : 0 : gcc_unreachable ();
438 : : }
439 : 1860 : *res_op = cond_op;
440 : 1860 : maybe_resimplify_conditional_op (seq, res_op, valueize);
441 : 1860 : return true;
442 : : }
443 : :
444 : : /* Helper for the autogenerated code, valueize OP. */
445 : :
446 : : tree
447 : 664503831 : do_valueize (tree (*valueize)(tree), tree op)
448 : : {
449 : 664503831 : if (valueize && TREE_CODE (op) == SSA_NAME)
450 : : {
451 : 495226142 : tree tem = valueize (op);
452 : 495226142 : if (tem)
453 : : return tem;
454 : : }
455 : : return op;
456 : : }
457 : :
458 : : /* Push the exploded expression described by RES_OP as a statement to
459 : : SEQ if necessary and return a gimple value denoting the value of the
460 : : expression. If RES is not NULL then the result will be always RES
461 : : and even gimple values are pushed to SEQ. */
462 : :
463 : : tree
464 : 12132326 : maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
465 : : {
466 : 12132326 : tree *ops = res_op->ops;
467 : 12132326 : unsigned num_ops = res_op->num_ops;
468 : :
469 : : /* The caller should have converted conditional operations into an UNCOND
470 : : form and resimplified as appropriate. The conditional form only
471 : : survives this far if that conversion failed. */
472 : 12132326 : if (res_op->cond.cond)
473 : : return NULL_TREE;
474 : :
475 : 12132089 : if (res_op->code.is_tree_code ())
476 : : {
477 : 12115885 : if (!res
478 : 12115885 : && gimple_simplified_result_is_gimple_val (res_op))
479 : 6791369 : return ops[0];
480 : 5324516 : if (mprts_hook)
481 : : {
482 : 2045151 : tree tem = mprts_hook (res_op);
483 : 2045151 : if (tem)
484 : : return tem;
485 : : }
486 : : }
487 : :
488 : 5282429 : if (!seq)
489 : : return NULL_TREE;
490 : :
491 : : /* Play safe and do not allow abnormals to be mentioned in
492 : : newly created statements. */
493 : 2046101 : for (unsigned int i = 0; i < num_ops; ++i)
494 : 1301897 : if (TREE_CODE (ops[i]) == SSA_NAME
495 : 1301897 : && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
496 : : return NULL_TREE;
497 : :
498 : 744204 : if (res_op->code.is_tree_code ())
499 : : {
500 : 730820 : auto code = tree_code (res_op->code);
501 : 730820 : if (!res)
502 : : {
503 : 650040 : if (gimple_in_ssa_p (cfun))
504 : 649001 : res = make_ssa_name (res_op->type);
505 : : else
506 : 1039 : res = create_tmp_reg (res_op->type);
507 : : }
508 : 730820 : maybe_build_generic_op (res_op);
509 : 1865810 : gimple *new_stmt = gimple_build_assign (res, code,
510 : : res_op->op_or_null (0),
511 : : res_op->op_or_null (1),
512 : : res_op->op_or_null (2));
513 : 730820 : gimple_seq_add_stmt_without_update (seq, new_stmt);
514 : 730820 : return res;
515 : : }
516 : : else
517 : : {
518 : 13384 : gcc_assert (num_ops != 0);
519 : 13384 : auto fn = combined_fn (res_op->code);
520 : 13384 : gcall *new_stmt = NULL;
521 : 13384 : if (internal_fn_p (fn))
522 : : {
523 : : /* Generate the given function if we can. */
524 : 8836 : internal_fn ifn = as_internal_fn (fn);
525 : :
526 : : /* We can't and should not emit calls to non-const functions. */
527 : 8836 : if (!(internal_fn_flags (ifn) & ECF_CONST))
528 : : return NULL_TREE;
529 : :
530 : 8836 : new_stmt = build_call_internal (ifn, res_op);
531 : 8836 : if (!new_stmt)
532 : : return NULL_TREE;
533 : : }
534 : : else
535 : : {
536 : : /* Find the function we want to call. */
537 : 4548 : tree decl = builtin_decl_implicit (as_builtin_fn (fn));
538 : 4548 : if (!decl)
539 : : return NULL;
540 : :
541 : : /* We can't and should not emit calls to non-const functions. */
542 : 4544 : if (!(flags_from_decl_or_type (decl) & ECF_CONST))
543 : : return NULL;
544 : :
545 : 7973 : new_stmt = gimple_build_call (decl, num_ops,
546 : : res_op->op_or_null (0),
547 : : res_op->op_or_null (1),
548 : : res_op->op_or_null (2),
549 : : res_op->op_or_null (3),
550 : : res_op->op_or_null (4));
551 : : }
552 : 12661 : if (!res)
553 : : {
554 : 1213 : if (gimple_in_ssa_p (cfun))
555 : 1213 : res = make_ssa_name (res_op->type);
556 : : else
557 : 0 : res = create_tmp_reg (res_op->type);
558 : : }
559 : 12661 : gimple_call_set_lhs (new_stmt, res);
560 : 12661 : gimple_seq_add_stmt_without_update (seq, new_stmt);
561 : 12661 : return res;
562 : : }
563 : : }
564 : :
565 : :
566 : : /* Public API overloads follow for operation being tree_code or
567 : : built_in_function and for one to three operands or arguments.
568 : : They return NULL_TREE if nothing could be simplified or
569 : : the resulting simplified value with parts pushed to SEQ.
570 : : If SEQ is NULL then if the simplification needs to create
571 : : new stmts it will fail. If VALUEIZE is non-NULL then all
572 : : SSA names will be valueized using that hook prior to
573 : : applying simplifications. */
574 : :
575 : : /* Unary ops. */
576 : :
577 : : tree
578 : 254396 : gimple_simplify (enum tree_code code, tree type,
579 : : tree op0,
580 : : gimple_seq *seq, tree (*valueize)(tree))
581 : : {
582 : 254396 : if (constant_for_folding (op0))
583 : : {
584 : 13042 : tree res = const_unop (code, type, op0);
585 : 13042 : if (res != NULL_TREE
586 : 13032 : && CONSTANT_CLASS_P (res))
587 : : return res;
588 : : }
589 : :
590 : 241364 : gimple_match_op res_op;
591 : 241364 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
592 : : return NULL_TREE;
593 : 8225 : return maybe_push_res_to_seq (&res_op, seq);
594 : : }
595 : :
596 : : /* Binary ops. */
597 : :
598 : : tree
599 : 24773272 : gimple_simplify (enum tree_code code, tree type,
600 : : tree op0, tree op1,
601 : : gimple_seq *seq, tree (*valueize)(tree))
602 : : {
603 : 24773272 : if (constant_for_folding (op0) && constant_for_folding (op1))
604 : : {
605 : 1693463 : tree res = const_binop (code, type, op0, op1);
606 : 1693463 : if (res != NULL_TREE
607 : 1692009 : && CONSTANT_CLASS_P (res))
608 : : return res;
609 : : }
610 : :
611 : : /* Canonicalize operand order both for matching and fallback stmt
612 : : generation. */
613 : 23081263 : if ((commutative_tree_code (code)
614 : 6570032 : || TREE_CODE_CLASS (code) == tcc_comparison)
615 : 29530106 : && tree_swap_operands_p (op0, op1))
616 : : {
617 : 44369 : std::swap (op0, op1);
618 : 44369 : if (TREE_CODE_CLASS (code) == tcc_comparison)
619 : 4286 : code = swap_tree_comparison (code);
620 : : }
621 : :
622 : 23081263 : gimple_match_op res_op;
623 : 23081263 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
624 : : return NULL_TREE;
625 : 2567507 : return maybe_push_res_to_seq (&res_op, seq);
626 : : }
627 : :
628 : : /* Ternary ops. */
629 : :
630 : : tree
631 : 41862 : gimple_simplify (enum tree_code code, tree type,
632 : : tree op0, tree op1, tree op2,
633 : : gimple_seq *seq, tree (*valueize)(tree))
634 : : {
635 : 42620 : if (constant_for_folding (op0) && constant_for_folding (op1)
636 : 42620 : && constant_for_folding (op2))
637 : : {
638 : 758 : tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
639 : 758 : if (res != NULL_TREE
640 : 758 : && CONSTANT_CLASS_P (res))
641 : : return res;
642 : : }
643 : :
644 : : /* Canonicalize operand order both for matching and fallback stmt
645 : : generation. */
646 : 41104 : if (commutative_ternary_tree_code (code)
647 : 41104 : && tree_swap_operands_p (op0, op1))
648 : : std::swap (op0, op1);
649 : :
650 : 41104 : gimple_match_op res_op;
651 : 41104 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
652 : : return NULL_TREE;
653 : 10664 : return maybe_push_res_to_seq (&res_op, seq);
654 : : }
655 : :
656 : : /* Builtin or internal function with one argument. */
657 : :
658 : : tree
659 : 23908 : gimple_simplify (combined_fn fn, tree type,
660 : : tree arg0,
661 : : gimple_seq *seq, tree (*valueize)(tree))
662 : : {
663 : 23908 : if (constant_for_folding (arg0))
664 : : {
665 : 0 : tree res = fold_const_call (fn, type, arg0);
666 : 0 : if (res && CONSTANT_CLASS_P (res))
667 : : return res;
668 : : }
669 : :
670 : 23908 : gimple_match_op res_op;
671 : 23908 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
672 : : return NULL_TREE;
673 : 0 : return maybe_push_res_to_seq (&res_op, seq);
674 : : }
675 : :
676 : : /* Builtin or internal function with two arguments. */
677 : :
678 : : tree
679 : 0 : gimple_simplify (combined_fn fn, tree type,
680 : : tree arg0, tree arg1,
681 : : gimple_seq *seq, tree (*valueize)(tree))
682 : : {
683 : 0 : if (constant_for_folding (arg0)
684 : 0 : && constant_for_folding (arg1))
685 : : {
686 : 0 : tree res = fold_const_call (fn, type, arg0, arg1);
687 : 0 : if (res && CONSTANT_CLASS_P (res))
688 : : return res;
689 : : }
690 : :
691 : 0 : gimple_match_op res_op;
692 : 0 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
693 : : return NULL_TREE;
694 : 0 : return maybe_push_res_to_seq (&res_op, seq);
695 : : }
696 : :
697 : : /* Builtin or internal function with three arguments. */
698 : :
699 : : tree
700 : 0 : gimple_simplify (combined_fn fn, tree type,
701 : : tree arg0, tree arg1, tree arg2,
702 : : gimple_seq *seq, tree (*valueize)(tree))
703 : : {
704 : 0 : if (constant_for_folding (arg0)
705 : 0 : && constant_for_folding (arg1)
706 : 0 : && constant_for_folding (arg2))
707 : : {
708 : 0 : tree res = fold_const_call (fn, type, arg0, arg1, arg2);
709 : 0 : if (res && CONSTANT_CLASS_P (res))
710 : : return res;
711 : : }
712 : :
713 : 0 : gimple_match_op res_op;
714 : 0 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
715 : : return NULL_TREE;
716 : 0 : return maybe_push_res_to_seq (&res_op, seq);
717 : : }
718 : :
719 : : /* Common subroutine of gimple_extract_op and gimple_simplify. Try to
720 : : describe STMT in RES_OP, returning true on success. Before recording
721 : : an operand, call:
722 : :
723 : : - VALUEIZE_OP for all top-level operand
724 : :
725 : : This routine takes a tree argument and returns a tree. */
726 : :
727 : : template<typename ValueizeOp>
728 : : inline bool
729 : 1307017916 : gimple_extract (gimple *stmt, gimple_match_op *res_op,
730 : : ValueizeOp valueize_op)
731 : : {
732 : 1307017916 : switch (gimple_code (stmt))
733 : : {
734 : 611341960 : case GIMPLE_ASSIGN:
735 : : {
736 : 611341960 : enum tree_code code = gimple_assign_rhs_code (stmt);
737 : 611341960 : tree type = TREE_TYPE (gimple_assign_lhs (stmt));
738 : 611341960 : switch (gimple_assign_rhs_class (stmt))
739 : : {
740 : 293283883 : case GIMPLE_SINGLE_RHS:
741 : 293283883 : if (code == REALPART_EXPR
742 : : || code == IMAGPART_EXPR
743 : 293283883 : || code == VIEW_CONVERT_EXPR)
744 : : {
745 : 7661902 : tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
746 : : /* op0 needs to be a SSA name or an min invariant. */
747 : 7661902 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
748 : : return false;
749 : 5462528 : res_op->set_op (code, type, valueize_op (op0));
750 : 5462528 : return true;
751 : : }
752 : 285621981 : else if (code == BIT_FIELD_REF)
753 : : {
754 : 1710616 : tree rhs1 = gimple_assign_rhs1 (stmt);
755 : 1710616 : tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
756 : : /* op0 needs to be a SSA name or an min invariant. */
757 : 1710616 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
758 : : return false;
759 : 891633 : res_op->set_op (code, type, op0,
760 : 891633 : TREE_OPERAND (rhs1, 1),
761 : 891633 : TREE_OPERAND (rhs1, 2),
762 : 891633 : REF_REVERSE_STORAGE_ORDER (rhs1));
763 : 891633 : return true;
764 : : }
765 : 283911365 : else if (code == SSA_NAME)
766 : : {
767 : 44363473 : tree op0 = gimple_assign_rhs1 (stmt);
768 : 44363473 : res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
769 : 44363473 : return true;
770 : : }
771 : : break;
772 : 80900813 : case GIMPLE_UNARY_RHS:
773 : : {
774 : 80900813 : tree rhs1 = gimple_assign_rhs1 (stmt);
775 : 80900813 : res_op->set_op (code, type, valueize_op (rhs1));
776 : 80900813 : return true;
777 : : }
778 : 236022210 : case GIMPLE_BINARY_RHS:
779 : : {
780 : 236022210 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
781 : 236022210 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
782 : 236022210 : res_op->set_op (code, type, rhs1, rhs2);
783 : 236022210 : return true;
784 : : }
785 : 1135054 : case GIMPLE_TERNARY_RHS:
786 : : {
787 : 1135054 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
788 : 1135054 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
789 : 1135054 : tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
790 : 1135054 : res_op->set_op (code, type, rhs1, rhs2, rhs3);
791 : 1135054 : return true;
792 : : }
793 : 0 : default:
794 : 0 : gcc_unreachable ();
795 : : }
796 : : break;
797 : : }
798 : :
799 : 69420474 : case GIMPLE_CALL:
800 : : /* ??? This way we can't simplify calls with side-effects. */
801 : 69420474 : if (gimple_call_lhs (stmt) != NULL_TREE
802 : 36416724 : && gimple_call_num_args (stmt) >= 1
803 : 103791340 : && gimple_call_num_args (stmt) <= 7)
804 : : {
805 : : combined_fn cfn;
806 : 34283683 : if (gimple_call_internal_p (stmt))
807 : 2495746 : cfn = as_combined_fn (gimple_call_internal_fn (stmt));
808 : : else
809 : : {
810 : 31787937 : tree fn = gimple_call_fn (stmt);
811 : 31787937 : if (!fn)
812 : : return false;
813 : :
814 : 31787937 : fn = valueize_op (fn);
815 : 31787937 : if (TREE_CODE (fn) != ADDR_EXPR
816 : 31787937 : || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
817 : : return false;
818 : :
819 : 30275911 : tree decl = TREE_OPERAND (fn, 0);
820 : 30275911 : if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
821 : 30275911 : || !gimple_builtin_call_types_compatible_p (stmt, decl))
822 : 19728669 : return false;
823 : :
824 : 10547242 : cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
825 : : }
826 : :
827 : 13042988 : unsigned int num_args = gimple_call_num_args (stmt);
828 : 13042988 : res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
829 : 42863881 : for (unsigned i = 0; i < num_args; ++i)
830 : 59519150 : res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
831 : : return true;
832 : : }
833 : : break;
834 : :
835 : 240824579 : case GIMPLE_COND:
836 : : {
837 : 240824579 : tree lhs = valueize_op (gimple_cond_lhs (stmt));
838 : 240824579 : tree rhs = valueize_op (gimple_cond_rhs (stmt));
839 : 240824579 : res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
840 : 240824579 : return true;
841 : : }
842 : :
843 : : default:
844 : : break;
845 : : }
846 : :
847 : : return false;
848 : : }
849 : :
850 : : /* Try to describe STMT in RES_OP, returning true on success.
851 : : For GIMPLE_CONDs, describe the condition that is being tested.
852 : : For GIMPLE_ASSIGNs, describe the rhs of the assignment.
853 : : For GIMPLE_CALLs, describe the call. */
854 : :
855 : : bool
856 : 1457732 : gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
857 : : {
858 : 1457732 : auto nop = [](tree op) { return op; };
859 : 1457732 : return gimple_extract (stmt, res_op, nop);
860 : : }
861 : :
862 : : /* The main STMT based simplification entry. It is used by the fold_stmt
863 : : and the fold_stmt_to_constant APIs. */
864 : :
865 : : bool
866 : 1305560184 : gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
867 : : tree (*valueize)(tree), tree (*top_valueize)(tree))
868 : : {
869 : 1305560184 : bool valueized = false;
870 : 2454896571 : auto valueize_op = [&](tree op)
871 : : {
872 : 1149336387 : return do_valueize (op, top_valueize, valueized);
873 : 1305560184 : };
874 : :
875 : 1305560184 : if (!gimple_extract (stmt, res_op, valueize_op))
876 : : return false;
877 : :
878 : 621736366 : if (res_op->code.is_internal_fn ())
879 : : {
880 : 2470668 : internal_fn ifn = internal_fn (res_op->code);
881 : 2470668 : if (try_conditional_simplification (ifn, res_op, seq, valueize))
882 : : return true;
883 : : }
884 : :
885 : 621734506 : if (!res_op->reverse
886 : 621734506 : && res_op->num_ops
887 : 1243469012 : && res_op->resimplify (seq, valueize))
888 : : return true;
889 : :
890 : 555460191 : return valueized;
891 : : }
892 : :
893 : : /* Helper that matches and simplifies the toplevel result from
894 : : a gimple_simplify run (where we don't want to build
895 : : a stmt in case it's used in in-place folding). Replaces
896 : : RES_OP with a simplified and/or canonicalized result and
897 : : returns whether any change was made. */
898 : :
899 : : static bool
900 : 150369867 : gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
901 : : tree (*valueize)(tree))
902 : : {
903 : 150369867 : if (constant_for_folding (res_op->ops[0]))
904 : : {
905 : 13166810 : tree tem = NULL_TREE;
906 : 13166810 : if (res_op->code.is_tree_code ())
907 : : {
908 : 11969518 : auto code = tree_code (res_op->code);
909 : 11969518 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
910 : 11155698 : && TREE_CODE_LENGTH (code) == 1)
911 : 11155698 : tem = const_unop (code, res_op->type, res_op->ops[0]);
912 : : }
913 : : else
914 : 1197292 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
915 : : res_op->ops[0]);
916 : 12352990 : if (tem != NULL_TREE
917 : 11099266 : && CONSTANT_CLASS_P (tem))
918 : : {
919 : 11099266 : if (TREE_OVERFLOW_P (tem))
920 : 3361 : tem = drop_tree_overflow (tem);
921 : 11099266 : res_op->set_value (tem);
922 : 11099266 : maybe_resimplify_conditional_op (seq, res_op, valueize);
923 : 11099266 : return true;
924 : : }
925 : : }
926 : :
927 : : /* Limit recursion, there are cases like PR80887 and others, for
928 : : example when value-numbering presents us with unfolded expressions
929 : : that we are really not prepared to handle without eventual
930 : : oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
931 : : itself as available expression. */
932 : 139270601 : static unsigned depth;
933 : 139270601 : if (depth > 10)
934 : : {
935 : 2 : if (dump_file && (dump_flags & TDF_FOLDING))
936 : 0 : fprintf (dump_file, "Aborting expression simplification due to "
937 : : "deep recursion\n");
938 : 2 : return false;
939 : : }
940 : :
941 : 139270599 : ++depth;
942 : 139270599 : gimple_match_op res_op2 (*res_op);
943 : 139270599 : if (gimple_simplify (&res_op2, seq, valueize,
944 : : res_op->code, res_op->type, res_op->ops[0]))
945 : : {
946 : 2492168 : --depth;
947 : 2492168 : *res_op = res_op2;
948 : 2492168 : return true;
949 : : }
950 : 136778431 : --depth;
951 : :
952 : 136778431 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
953 : : return true;
954 : :
955 : : return false;
956 : : }
957 : :
958 : : /* Helper that matches and simplifies the toplevel result from
959 : : a gimple_simplify run (where we don't want to build
960 : : a stmt in case it's used in in-place folding). Replaces
961 : : RES_OP with a simplified and/or canonicalized result and
962 : : returns whether any change was made. */
963 : :
964 : : static bool
965 : 503859718 : gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
966 : : tree (*valueize)(tree))
967 : : {
968 : 503859718 : if (constant_for_folding (res_op->ops[0])
969 : 503859718 : && constant_for_folding (res_op->ops[1]))
970 : : {
971 : 21665142 : tree tem = NULL_TREE;
972 : 21665142 : if (res_op->code.is_tree_code ())
973 : : {
974 : 21536137 : auto code = tree_code (res_op->code);
975 : 21536137 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
976 : 21536137 : && TREE_CODE_LENGTH (code) == 2)
977 : 21536137 : tem = const_binop (code, res_op->type,
978 : : res_op->ops[0], res_op->ops[1]);
979 : : }
980 : : else
981 : 129005 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
982 : : res_op->ops[0], res_op->ops[1]);
983 : 21665142 : if (tem != NULL_TREE
984 : 21484633 : && CONSTANT_CLASS_P (tem))
985 : : {
986 : 21484587 : if (TREE_OVERFLOW_P (tem))
987 : 633 : tem = drop_tree_overflow (tem);
988 : 21484587 : res_op->set_value (tem);
989 : 21484587 : maybe_resimplify_conditional_op (seq, res_op, valueize);
990 : 21484587 : return true;
991 : : }
992 : : }
993 : :
994 : : /* Canonicalize operand order. */
995 : 482375131 : bool canonicalized = false;
996 : 482375131 : bool is_comparison
997 : 482375131 : = (res_op->code.is_tree_code ()
998 : 482375131 : && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison);
999 : 228399933 : if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type))
1000 : 419766355 : && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
1001 : : {
1002 : 8731527 : std::swap (res_op->ops[0], res_op->ops[1]);
1003 : 8731527 : if (is_comparison)
1004 : 3238695 : res_op->code = swap_tree_comparison (tree_code (res_op->code));
1005 : : canonicalized = true;
1006 : : }
1007 : :
1008 : : /* Limit recursion, see gimple_resimplify1. */
1009 : 482375131 : static unsigned depth;
1010 : 482375131 : if (depth > 10)
1011 : : {
1012 : 32563 : if (dump_file && (dump_flags & TDF_FOLDING))
1013 : 0 : fprintf (dump_file, "Aborting expression simplification due to "
1014 : : "deep recursion\n");
1015 : 32563 : return false;
1016 : : }
1017 : :
1018 : 482342568 : ++depth;
1019 : 482342568 : gimple_match_op res_op2 (*res_op);
1020 : 482342568 : if (gimple_simplify (&res_op2, seq, valueize,
1021 : : res_op->code, res_op->type,
1022 : : res_op->ops[0], res_op->ops[1]))
1023 : : {
1024 : 38648341 : --depth;
1025 : 38648341 : *res_op = res_op2;
1026 : 38648341 : return true;
1027 : : }
1028 : 443694227 : --depth;
1029 : :
1030 : 443694227 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1031 : : return true;
1032 : :
1033 : : return canonicalized;
1034 : : }
1035 : :
1036 : : /* Helper that matches and simplifies the toplevel result from
1037 : : a gimple_simplify run (where we don't want to build
1038 : : a stmt in case it's used in in-place folding). Replaces
1039 : : RES_OP with a simplified and/or canonicalized result and
1040 : : returns whether any change was made. */
1041 : :
1042 : : static bool
1043 : 6375060 : gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
1044 : : tree (*valueize)(tree))
1045 : : {
1046 : 6375060 : if (constant_for_folding (res_op->ops[0])
1047 : 279995 : && constant_for_folding (res_op->ops[1])
1048 : 6464069 : && constant_for_folding (res_op->ops[2]))
1049 : : {
1050 : 81379 : tree tem = NULL_TREE;
1051 : 81379 : if (res_op->code.is_tree_code ())
1052 : : {
1053 : 43785 : auto code = tree_code (res_op->code);
1054 : 43785 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
1055 : 43785 : && TREE_CODE_LENGTH (code) == 3)
1056 : 43785 : tem = fold_ternary/*_to_constant*/ (code, res_op->type,
1057 : : res_op->ops[0], res_op->ops[1],
1058 : : res_op->ops[2]);
1059 : : }
1060 : : else
1061 : 37594 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
1062 : : res_op->ops[0], res_op->ops[1], res_op->ops[2]);
1063 : 81379 : if (tem != NULL_TREE
1064 : 44758 : && CONSTANT_CLASS_P (tem))
1065 : : {
1066 : 44646 : if (TREE_OVERFLOW_P (tem))
1067 : 4 : tem = drop_tree_overflow (tem);
1068 : 44646 : res_op->set_value (tem);
1069 : 44646 : maybe_resimplify_conditional_op (seq, res_op, valueize);
1070 : 44646 : return true;
1071 : : }
1072 : : }
1073 : :
1074 : : /* Canonicalize operand order. */
1075 : 6330414 : bool canonicalized = false;
1076 : 6330414 : int argno = first_commutative_argument (res_op->code, res_op->type);
1077 : 6330414 : if (argno >= 0
1078 : 6330414 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1079 : : {
1080 : 1206 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1081 : 1206 : canonicalized = true;
1082 : : }
1083 : :
1084 : : /* Limit recursion, see gimple_resimplify1. */
1085 : 6330414 : static unsigned depth;
1086 : 6330414 : if (depth > 10)
1087 : : {
1088 : 33 : if (dump_file && (dump_flags & TDF_FOLDING))
1089 : 0 : fprintf (dump_file, "Aborting expression simplification due to "
1090 : : "deep recursion\n");
1091 : 33 : return false;
1092 : : }
1093 : :
1094 : 6330381 : ++depth;
1095 : 6330381 : gimple_match_op res_op2 (*res_op);
1096 : 6330381 : if (gimple_simplify (&res_op2, seq, valueize,
1097 : : res_op->code, res_op->type,
1098 : : res_op->ops[0], res_op->ops[1], res_op->ops[2]))
1099 : : {
1100 : 410777 : --depth;
1101 : 410777 : *res_op = res_op2;
1102 : 410777 : return true;
1103 : : }
1104 : 5919604 : --depth;
1105 : :
1106 : 5919604 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1107 : : return true;
1108 : :
1109 : : return canonicalized;
1110 : : }
1111 : :
1112 : : /* Helper that matches and simplifies the toplevel result from
1113 : : a gimple_simplify run (where we don't want to build
1114 : : a stmt in case it's used in in-place folding). Replaces
1115 : : RES_OP with a simplified and/or canonicalized result and
1116 : : returns whether any change was made. */
1117 : :
1118 : : static bool
1119 : 249771 : gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
1120 : : tree (*valueize)(tree))
1121 : : {
1122 : : /* No constant folding is defined for four-operand functions. */
1123 : :
1124 : : /* Canonicalize operand order. */
1125 : 249771 : bool canonicalized = false;
1126 : 249771 : int argno = first_commutative_argument (res_op->code, res_op->type);
1127 : 249771 : if (argno >= 0
1128 : 249771 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1129 : : {
1130 : 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1131 : 0 : canonicalized = true;
1132 : : }
1133 : :
1134 : : /* Limit recursion, see gimple_resimplify1. */
1135 : 249771 : static unsigned depth;
1136 : 249771 : if (depth > 10)
1137 : : {
1138 : 0 : if (dump_file && (dump_flags & TDF_FOLDING))
1139 : 0 : fprintf (dump_file, "Aborting expression simplification due to "
1140 : : "deep recursion\n");
1141 : 0 : return false;
1142 : : }
1143 : :
1144 : 249771 : ++depth;
1145 : 249771 : gimple_match_op res_op2 (*res_op);
1146 : 249771 : if (gimple_simplify (&res_op2, seq, valueize,
1147 : : res_op->code, res_op->type,
1148 : : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1149 : : res_op->ops[3]))
1150 : : {
1151 : 0 : --depth;
1152 : 0 : *res_op = res_op2;
1153 : 0 : return true;
1154 : : }
1155 : 249771 : --depth;
1156 : :
1157 : 249771 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1158 : : return true;
1159 : :
1160 : : return canonicalized;
1161 : : }
1162 : :
1163 : : /* Helper that matches and simplifies the toplevel result from
1164 : : a gimple_simplify run (where we don't want to build
1165 : : a stmt in case it's used in in-place folding). Replaces
1166 : : RES_OP with a simplified and/or canonicalized result and
1167 : : returns whether any change was made. */
1168 : :
1169 : : static bool
1170 : 25656 : gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
1171 : : tree (*valueize)(tree))
1172 : : {
1173 : : /* No constant folding is defined for five-operand functions. */
1174 : :
1175 : : /* Canonicalize operand order. */
1176 : 25656 : bool canonicalized = false;
1177 : 25656 : int argno = first_commutative_argument (res_op->code, res_op->type);
1178 : 25656 : if (argno >= 0
1179 : 25656 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1180 : : {
1181 : 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1182 : 0 : canonicalized = true;
1183 : : }
1184 : :
1185 : 25656 : gimple_match_op res_op2 (*res_op);
1186 : 25656 : if (gimple_simplify (&res_op2, seq, valueize,
1187 : : res_op->code, res_op->type,
1188 : : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1189 : : res_op->ops[3], res_op->ops[4]))
1190 : : {
1191 : 0 : *res_op = res_op2;
1192 : 0 : return true;
1193 : : }
1194 : :
1195 : 25656 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1196 : : return true;
1197 : :
1198 : : return canonicalized;
1199 : : }
1200 : :
1201 : : /* Helper that matches and simplifies the toplevel result from
1202 : : a gimple_simplify run (where we don't want to build
1203 : : a stmt in case it's used in in-place folding). Replaces
1204 : : RES_OP with a simplified and/or canonicalized result and
1205 : : returns whether any change was made. */
1206 : :
1207 : : static bool
1208 : 611848 : gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
1209 : : tree (*valueize)(tree))
1210 : : {
1211 : : /* No constant folding is defined for six-operand functions. */
1212 : :
1213 : : /* Canonicalize operand order. */
1214 : 611848 : bool canonicalized = false;
1215 : 611848 : int argno = first_commutative_argument (res_op->code, res_op->type);
1216 : 611848 : if (argno >= 0
1217 : 611848 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1218 : : {
1219 : 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1220 : 0 : canonicalized = true;
1221 : : }
1222 : :
1223 : 611848 : gimple_match_op res_op2 (*res_op);
1224 : 611848 : if (gimple_simplify (&res_op2, seq, valueize,
1225 : : res_op->code, res_op->type,
1226 : : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1227 : : res_op->ops[3], res_op->ops[4], res_op->ops[5]))
1228 : : {
1229 : 0 : *res_op = res_op2;
1230 : 0 : return true;
1231 : : }
1232 : :
1233 : 611848 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1234 : : return true;
1235 : :
1236 : : return canonicalized;
1237 : : }
1238 : :
1239 : : /* Helper that matches and simplifies the toplevel result from
1240 : : a gimple_simplify run (where we don't want to build
1241 : : a stmt in case it's used in in-place folding). Replaces
1242 : : RES_OP with a simplified and/or canonicalized result and
1243 : : returns whether any change was made. */
1244 : :
1245 : : static bool
1246 : 82367 : gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
1247 : : tree (*valueize)(tree))
1248 : : {
1249 : : /* No constant folding is defined for seven-operand functions. */
1250 : :
1251 : : /* Canonicalize operand order. */
1252 : 82367 : bool canonicalized = false;
1253 : 82367 : int argno = first_commutative_argument (res_op->code, res_op->type);
1254 : 82367 : if (argno >= 0
1255 : 82367 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1256 : : {
1257 : 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1258 : 0 : canonicalized = true;
1259 : : }
1260 : :
1261 : 82367 : gimple_match_op res_op2 (*res_op);
1262 : 82367 : if (gimple_simplify (&res_op2, seq, valueize,
1263 : : res_op->code, res_op->type,
1264 : : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1265 : : res_op->ops[3], res_op->ops[4], res_op->ops[5],
1266 : : res_op->ops[6]))
1267 : : {
1268 : 0 : *res_op = res_op2;
1269 : 0 : return true;
1270 : : }
1271 : :
1272 : 82367 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1273 : : return true;
1274 : :
1275 : : return canonicalized;
1276 : : }
1277 : :
1278 : : /* Return a canonical form for CODE when operating on TYPE. The idea
1279 : : is to remove redundant ways of representing the same operation so
1280 : : that code_helpers can be hashed and compared for equality.
1281 : :
1282 : : The only current canonicalization is to replace built-in functions
1283 : : with internal functions, in cases where internal-fn.def defines
1284 : : such an internal function.
1285 : :
1286 : : Note that the new code_helper cannot necessarily be used in place of
1287 : : the original code_helper. For example, the new code_helper might be
1288 : : an internal function that the target does not support. */
1289 : :
1290 : : code_helper
1291 : 76144 : canonicalize_code (code_helper code, tree type)
1292 : : {
1293 : 76144 : if (code.is_fn_code ())
1294 : 3499 : return associated_internal_fn (combined_fn (code), type);
1295 : 72645 : return code;
1296 : : }
1297 : :
1298 : : /* Return true if CODE is a binary operation and if CODE is commutative when
1299 : : operating on type TYPE. */
1300 : :
1301 : : bool
1302 : 228439151 : commutative_binary_op_p (code_helper code, tree type)
1303 : : {
1304 : 228439151 : if (code.is_tree_code ())
1305 : 222426747 : return commutative_tree_code (tree_code (code));
1306 : 6012404 : auto cfn = combined_fn (code);
1307 : 6012404 : return commutative_binary_fn_p (associated_internal_fn (cfn, type));
1308 : : }
1309 : :
1310 : : /* Return true if CODE represents a ternary operation and if the first two
1311 : : operands are commutative when CODE is operating on TYPE. */
1312 : :
1313 : : bool
1314 : 0 : commutative_ternary_op_p (code_helper code, tree type)
1315 : : {
1316 : 0 : if (code.is_tree_code ())
1317 : 0 : return commutative_ternary_tree_code (tree_code (code));
1318 : 0 : auto cfn = combined_fn (code);
1319 : 0 : return commutative_ternary_fn_p (associated_internal_fn (cfn, type));
1320 : : }
1321 : :
1322 : : /* If CODE is commutative in two consecutive operands, return the
1323 : : index of the first, otherwise return -1. */
1324 : :
1325 : : int
1326 : 7300056 : first_commutative_argument (code_helper code, tree type)
1327 : : {
1328 : 7300056 : if (code.is_tree_code ())
1329 : : {
1330 : 3202104 : auto tcode = tree_code (code);
1331 : 3202104 : if (commutative_tree_code (tcode)
1332 : 3202104 : || commutative_ternary_tree_code (tcode))
1333 : 1588 : return 0;
1334 : : return -1;
1335 : : }
1336 : 4097952 : auto cfn = combined_fn (code);
1337 : 4097952 : return first_commutative_argument (associated_internal_fn (cfn, type));
1338 : : }
1339 : :
1340 : : /* Return true if CODE is a binary operation that is associative when
1341 : : operating on type TYPE. */
1342 : :
1343 : : bool
1344 : 39072 : associative_binary_op_p (code_helper code, tree type)
1345 : : {
1346 : 39072 : if (code.is_tree_code ())
1347 : 39024 : return associative_tree_code (tree_code (code));
1348 : 48 : auto cfn = combined_fn (code);
1349 : 48 : return associative_binary_fn_p (associated_internal_fn (cfn, type));
1350 : : }
1351 : :
1352 : : /* Return true if the target directly supports operation CODE on type TYPE.
1353 : : QUERY_TYPE acts as for optab_for_tree_code. */
1354 : :
1355 : : bool
1356 : 293669 : directly_supported_p (code_helper code, tree type, optab_subtype query_type)
1357 : : {
1358 : 293669 : if (code.is_tree_code ())
1359 : : {
1360 : 292172 : direct_optab optab = optab_for_tree_code (tree_code (code), type,
1361 : : query_type);
1362 : 292172 : return (optab != unknown_optab
1363 : 292172 : && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing);
1364 : : }
1365 : 1497 : gcc_assert (query_type == optab_default
1366 : : || (query_type == optab_vector && VECTOR_TYPE_P (type))
1367 : : || (query_type == optab_scalar && !VECTOR_TYPE_P (type)));
1368 : 1497 : internal_fn ifn = associated_internal_fn (combined_fn (code), type);
1369 : 1497 : return (direct_internal_fn_p (ifn)
1370 : 1497 : && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
1371 : : }
1372 : :
1373 : : /* As above, overloading the function for conversion-type optabs. */
1374 : : bool
1375 : 867 : directly_supported_p (code_helper code, tree otype, tree itype,
1376 : : optab_subtype query_type)
1377 : : {
1378 : 867 : if (code.is_tree_code ())
1379 : : {
1380 : 867 : convert_optab optab = optab_for_tree_code (tree_code (code), itype,
1381 : : query_type);
1382 : 867 : return (optab != unknown_optab
1383 : 1734 : && convert_optab_handler (optab, TYPE_MODE (otype),
1384 : 867 : TYPE_MODE (itype)) != CODE_FOR_nothing);
1385 : : }
1386 : 0 : gcc_assert (query_type == optab_default
1387 : : || (query_type == optab_vector && VECTOR_TYPE_P (itype))
1388 : : || (query_type == optab_scalar && !VECTOR_TYPE_P (itype)));
1389 : 0 : internal_fn ifn = associated_internal_fn (combined_fn (code), itype);
1390 : 0 : return (direct_internal_fn_p (ifn)
1391 : 0 : && direct_internal_fn_supported_p (ifn, tree_pair (otype, itype),
1392 : : OPTIMIZE_FOR_SPEED));
1393 : : }
1394 : :
1395 : :
1396 : : /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn
1397 : : for a code_helper CODE operating on type TYPE. */
1398 : :
1399 : : internal_fn
1400 : 2305 : get_conditional_internal_fn (code_helper code, tree type)
1401 : : {
1402 : 2305 : if (code.is_tree_code ())
1403 : 2030 : return get_conditional_internal_fn (tree_code (code));
1404 : 275 : auto cfn = combined_fn (code);
1405 : 275 : return get_conditional_internal_fn (associated_internal_fn (cfn, type));
1406 : : }
|