Line data Source code
1 : /* Helpers for the autogenerated gimple-match.cc file.
2 : Copyright (C) 2023-2026 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 677829481 : gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
107 : {
108 677829481 : switch (num_ops)
109 : {
110 153165557 : case 1:
111 153165557 : return gimple_resimplify1 (seq, this, valueize);
112 516793559 : case 2:
113 516793559 : return gimple_resimplify2 (seq, this, valueize);
114 6913221 : case 3:
115 6913221 : return gimple_resimplify3 (seq, this, valueize);
116 245440 : case 4:
117 245440 : return gimple_resimplify4 (seq, this, valueize);
118 24732 : case 5:
119 24732 : return gimple_resimplify5 (seq, this, valueize);
120 603093 : case 6:
121 603093 : return gimple_resimplify6 (seq, this, valueize);
122 83879 : case 7:
123 83879 : 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 590814 : gimple_match_op::operands_occurs_in_abnormal_phi() const
133 : {
134 1650360 : for (unsigned int i = 0; i < num_ops; i++)
135 : {
136 1059546 : if (TREE_CODE (ops[i]) == SSA_NAME
137 1059546 : && 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 735198929 : constant_for_folding (tree t)
148 : {
149 735198929 : return (CONSTANT_CLASS_P (t)
150 : /* The following is only interesting to string builtins. */
151 735198929 : || (TREE_CODE (t) == ADDR_EXPR
152 13522688 : && 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 12691 : convert_conditional_op (gimple_match_op *orig_op,
160 : gimple_match_op *new_op)
161 : {
162 12691 : internal_fn ifn;
163 12691 : if (orig_op->code.is_tree_code ())
164 11541 : ifn = get_conditional_internal_fn ((tree_code) orig_op->code);
165 : else
166 : {
167 1150 : auto cfn = combined_fn (orig_op->code);
168 1150 : if (!internal_fn_p (cfn))
169 : return false;
170 1150 : ifn = get_conditional_internal_fn (as_internal_fn (cfn));
171 : }
172 12691 : if (ifn == IFN_LAST)
173 : return false;
174 11101 : unsigned int num_ops = orig_op->num_ops;
175 11101 : unsigned int num_cond_ops = 2;
176 11101 : 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 11101 : new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + num_cond_ops);
183 11101 : new_op->ops[0] = orig_op->cond.cond;
184 34450 : for (unsigned int i = 0; i < num_ops; ++i)
185 23349 : new_op->ops[i + 1] = orig_op->ops[i];
186 11101 : tree else_value = orig_op->cond.else_value;
187 : /* Some patterns convert operand types, e.g. from float to int.
188 : If we had a real else value before (e.g. float) it won't match
189 : the type. Verify that here. */
190 11101 : if (else_value
191 11101 : && !types_compatible_p (orig_op->type, TREE_TYPE (else_value)))
192 : return false;
193 :
194 11101 : if (!else_value)
195 6 : else_value = targetm.preferred_else_value (ifn, orig_op->type,
196 6 : num_ops, orig_op->ops);
197 11101 : new_op->ops[num_ops + 1] = else_value;
198 11101 : if (orig_op->cond.len)
199 : {
200 0 : new_op->ops[num_ops + 2] = orig_op->cond.len;
201 0 : new_op->ops[num_ops + 3] = orig_op->cond.bias;
202 : }
203 : return true;
204 : }
205 : /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
206 : VALUEIZED to true if valueization changed OP. */
207 :
208 : inline tree
209 1177264586 : do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
210 : {
211 1177264586 : if (valueize && TREE_CODE (op) == SSA_NAME)
212 : {
213 743149618 : tree tem = valueize (op);
214 743149618 : if (tem && tem != op)
215 : {
216 51926866 : op = tem;
217 51926866 : valueized = true;
218 : }
219 : }
220 1177264586 : return op;
221 : }
222 :
223 : /* If in GIMPLE the operation described by RES_OP should be single-rhs,
224 : build a GENERIC tree for that expression and update RES_OP accordingly. */
225 :
226 : void
227 2893831 : maybe_build_generic_op (gimple_match_op *res_op)
228 : {
229 2893831 : tree_code code = (tree_code) res_op->code;
230 2893831 : tree val;
231 2893831 : switch (code)
232 : {
233 10168 : case REALPART_EXPR:
234 10168 : case IMAGPART_EXPR:
235 10168 : case VIEW_CONVERT_EXPR:
236 10168 : val = build1 (code, res_op->type, res_op->ops[0]);
237 10168 : res_op->set_value (val);
238 10168 : break;
239 83071 : case BIT_FIELD_REF:
240 83071 : val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
241 : res_op->ops[2]);
242 83071 : REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
243 83071 : res_op->set_value (val);
244 83071 : break;
245 2893831 : default:;
246 : }
247 2893831 : }
248 :
249 : /* Try to build RES_OP, which is known to be a call to FN. Return null
250 : if the target doesn't support the function. */
251 :
252 : static gcall *
253 8233 : build_call_internal (internal_fn fn, gimple_match_op *res_op)
254 : {
255 8233 : if (direct_internal_fn_p (fn))
256 : {
257 8201 : tree_pair types = direct_internal_fn_types (fn, res_op->type,
258 8201 : res_op->ops);
259 8201 : if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
260 : {
261 76 : switch (fn)
262 : {
263 2 : case IFN_CLZ:
264 2 : case IFN_CTZ:
265 2 : case IFN_CLRSB:
266 2 : case IFN_FFS:
267 2 : case IFN_POPCOUNT:
268 2 : case IFN_PARITY:
269 : /* For these 6 builtins large/huge _BitInt operand is ok
270 : before bitint lowering pass. */
271 2 : if (res_op->num_ops >= 1
272 2 : && TREE_CODE (TREE_TYPE (res_op->ops[0])) == BITINT_TYPE
273 2 : && (TYPE_PRECISION (TREE_TYPE (res_op->ops[0]))
274 4 : > MAX_FIXED_MODE_SIZE)
275 2 : && cfun
276 4 : && (cfun->curr_properties & PROP_gimple_lbitint) == 0)
277 : break;
278 74 : return NULL;
279 :
280 : default:
281 : return NULL;
282 : }
283 : }
284 : }
285 32970 : return gimple_build_call_internal (fn, res_op->num_ops,
286 : res_op->op_or_null (0),
287 : res_op->op_or_null (1),
288 : res_op->op_or_null (2),
289 : res_op->op_or_null (3),
290 : res_op->op_or_null (4),
291 : res_op->op_or_null (5),
292 8159 : res_op->op_or_null (6));
293 : }
294 :
295 : /* RES_OP is the result of a simplification. If it is conditional,
296 : try to replace it with the equivalent UNCOND form, such as an
297 : IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the
298 : result of the replacement if appropriate, adding any new statements to
299 : SEQ and using VALUEIZE as the valueization function. Return true if
300 : this resimplification occurred and resulted in at least one change. */
301 :
302 : static bool
303 635998062 : maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
304 : tree (*valueize) (tree))
305 : {
306 635998062 : if (!res_op->cond.cond)
307 : return false;
308 :
309 15710 : if (!res_op->cond.else_value
310 15710 : && res_op->code.is_tree_code ())
311 : {
312 : /* The "else" value doesn't matter. If the "then" value is a
313 : gimple value, just use it unconditionally. This isn't a
314 : simplification in itself, since there was no operation to
315 : build in the first place. */
316 1772 : if (gimple_simplified_result_is_gimple_val (res_op))
317 : {
318 1760 : res_op->cond.cond = NULL_TREE;
319 1760 : return false;
320 : }
321 :
322 : /* Likewise if the operation would not trap. */
323 12 : bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
324 12 : && TYPE_OVERFLOW_TRAPS (res_op->type));
325 12 : tree_code op_code = (tree_code) res_op->code;
326 12 : bool op_could_trap;
327 :
328 : /* COND_EXPR will trap if, and only if, the condition
329 : traps and hence we have to check this. For all other operations, we
330 : don't need to consider the operands. */
331 12 : if (op_code == COND_EXPR)
332 0 : op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
333 : else
334 24 : op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
335 12 : FLOAT_TYPE_P (res_op->type),
336 : honor_trapv,
337 : res_op->op_or_null (1));
338 :
339 12 : if (!op_could_trap)
340 : {
341 6 : res_op->cond.cond = NULL_TREE;
342 6 : return false;
343 : }
344 : }
345 :
346 : /* If the "then" value is a gimple value and the "else" value matters,
347 : create a (VEC_)COND_EXPR between them, then see if it can be further
348 : simplified. */
349 13944 : gimple_match_op new_op;
350 13944 : if (res_op->cond.else_value
351 13944 : && gimple_simplified_result_is_gimple_val (res_op))
352 : {
353 1253 : if (VECTOR_TYPE_P (res_op->type))
354 : {
355 1253 : tree len = res_op->cond.len;
356 1253 : if (!len)
357 1253 : new_op.set_op (VEC_COND_EXPR, res_op->type,
358 : res_op->cond.cond, res_op->ops[0],
359 : res_op->cond.else_value);
360 : else
361 0 : new_op.set_op (IFN_VCOND_MASK_LEN, res_op->type,
362 : res_op->cond.cond, res_op->ops[0],
363 : res_op->cond.else_value,
364 : res_op->cond.len, res_op->cond.bias);
365 : }
366 : else
367 0 : new_op.set_op (COND_EXPR, res_op->type,
368 : res_op->cond.cond, res_op->ops[0],
369 : res_op->cond.else_value);
370 1253 : *res_op = new_op;
371 1253 : return gimple_resimplify3 (seq, res_op, valueize);
372 : }
373 :
374 : /* Otherwise try rewriting the operation as an IFN_COND_* call.
375 : Again, this isn't a simplification in itself, since it's what
376 : RES_OP already described. */
377 12691 : if (convert_conditional_op (res_op, &new_op))
378 11101 : *res_op = new_op;
379 :
380 : return false;
381 : }
382 :
383 : /* If RES_OP is a call to a conditional internal function, try simplifying
384 : the associated unconditional operation and using the result to build
385 : a new conditional operation. For example, if RES_OP is:
386 :
387 : IFN_COND_ADD (COND, A, B, ELSE)
388 :
389 : try simplifying (plus A B) and using the result to build a replacement
390 : for the whole IFN_COND_ADD.
391 :
392 : Return true if this approach led to a simplification, otherwise leave
393 : RES_OP unchanged (and so suitable for other simplifications). When
394 : returning true, add any new statements to SEQ and use VALUEIZE as the
395 : valueization function.
396 :
397 : RES_OP is known to be a call to IFN. */
398 :
399 : static bool
400 3019822 : try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
401 : gimple_seq *seq, tree (*valueize) (tree))
402 : {
403 3019822 : code_helper op;
404 3019822 : tree_code code = conditional_internal_fn_code (ifn);
405 3019822 : int len_index = internal_fn_len_index (ifn);
406 3019822 : if (code != ERROR_MARK)
407 11993 : op = code;
408 : else
409 : {
410 3007829 : ifn = get_unconditional_internal_fn (ifn);
411 3007829 : if (ifn == IFN_LAST)
412 : return false;
413 1150 : op = as_combined_fn (ifn);
414 : }
415 :
416 13143 : unsigned int num_ops = res_op->num_ops;
417 : /* num_cond_ops = 2 for COND_ADD (MASK and ELSE)
418 : wheras num_cond_ops = 4 for COND_LEN_ADD (MASK, ELSE, LEN and BIAS). */
419 13143 : unsigned int num_cond_ops = len_index < 0 ? 2 : 4;
420 13143 : tree else_value
421 13143 : = len_index < 0 ? res_op->ops[num_ops - 1] : res_op->ops[num_ops - 3];
422 13143 : tree len = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 2];
423 0 : tree bias = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 1];
424 13143 : gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
425 13143 : else_value, len, bias),
426 13143 : op, res_op->type, num_ops - num_cond_ops);
427 :
428 13143 : memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
429 13143 : switch (num_ops - num_cond_ops)
430 : {
431 0 : case 1:
432 0 : if (!gimple_resimplify1 (seq, &cond_op, valueize))
433 : return false;
434 : break;
435 11993 : case 2:
436 11993 : if (!gimple_resimplify2 (seq, &cond_op, valueize))
437 : return false;
438 : break;
439 1150 : case 3:
440 1150 : if (!gimple_resimplify3 (seq, &cond_op, valueize))
441 : return false;
442 : break;
443 0 : default:
444 0 : gcc_unreachable ();
445 : }
446 2940 : *res_op = cond_op;
447 2940 : maybe_resimplify_conditional_op (seq, res_op, valueize);
448 2940 : return true;
449 : }
450 :
451 : /* Helper for the autogenerated code, valueize OP. */
452 :
453 : tree
454 699100593 : do_valueize (tree (*valueize)(tree), tree op)
455 : {
456 699100593 : if (valueize && TREE_CODE (op) == SSA_NAME)
457 : {
458 519346722 : tree tem = valueize (op);
459 519346722 : if (tem)
460 : return tem;
461 : }
462 : return op;
463 : }
464 :
465 : /* Push the exploded expression described by RES_OP as a statement to
466 : SEQ if necessary and return a gimple value denoting the value of the
467 : expression. If RES is not NULL then the result will be always RES
468 : and even gimple values are pushed to SEQ. */
469 :
470 : tree
471 12453630 : maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
472 : {
473 12453630 : tree *ops = res_op->ops;
474 12453630 : unsigned num_ops = res_op->num_ops;
475 :
476 : /* The caller should have converted conditional operations into an UNCOND
477 : form and resimplified as appropriate. The conditional form only
478 : survives this far if that conversion failed. */
479 12453630 : if (res_op->cond.cond)
480 : return NULL_TREE;
481 :
482 12453231 : if (res_op->code.is_tree_code ())
483 : {
484 12437572 : if (!res
485 12437572 : && gimple_simplified_result_is_gimple_val (res_op))
486 6924384 : return ops[0];
487 5513188 : if (mprts_hook)
488 : {
489 2121128 : tree tem = mprts_hook (res_op);
490 2121128 : if (tem)
491 : return tem;
492 : }
493 : }
494 :
495 5474707 : if (!seq)
496 : return NULL_TREE;
497 :
498 : /* Play safe and do not allow abnormals to be mentioned in
499 : newly created statements. */
500 2104768 : for (unsigned int i = 0; i < num_ops; ++i)
501 1338018 : if (TREE_CODE (ops[i]) == SSA_NAME
502 1338018 : && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
503 : return NULL_TREE;
504 :
505 766750 : if (res_op->code.is_tree_code ())
506 : {
507 753919 : auto code = tree_code (res_op->code);
508 753919 : if (!res)
509 : {
510 672991 : if (gimple_in_ssa_p (cfun))
511 672013 : res = make_ssa_name (res_op->type);
512 : else
513 978 : res = create_tmp_reg (res_op->type);
514 : }
515 753919 : maybe_build_generic_op (res_op);
516 1924351 : gimple *new_stmt = gimple_build_assign (res, code,
517 : res_op->op_or_null (0),
518 : res_op->op_or_null (1),
519 : res_op->op_or_null (2));
520 753919 : gimple_seq_add_stmt_without_update (seq, new_stmt);
521 753919 : return res;
522 : }
523 : else
524 : {
525 12831 : gcc_assert (num_ops != 0);
526 12831 : auto fn = combined_fn (res_op->code);
527 12831 : gcall *new_stmt = NULL;
528 12831 : if (internal_fn_p (fn))
529 : {
530 : /* Generate the given function if we can. */
531 8233 : internal_fn ifn = as_internal_fn (fn);
532 :
533 : /* We can't and should not emit calls to non-const functions. */
534 8233 : if (!(internal_fn_flags (ifn) & ECF_CONST))
535 : return NULL_TREE;
536 :
537 8233 : new_stmt = build_call_internal (ifn, res_op);
538 8233 : if (!new_stmt)
539 : return NULL_TREE;
540 : }
541 : else
542 : {
543 : /* Find the function we want to call. */
544 4598 : tree decl = builtin_decl_implicit (as_builtin_fn (fn));
545 4598 : if (!decl)
546 : return NULL;
547 :
548 : /* We can't and should not emit calls to non-const functions. */
549 4594 : if (!(flags_from_decl_or_type (decl) & ECF_CONST))
550 : return NULL;
551 :
552 8085 : new_stmt = gimple_build_call (decl, num_ops,
553 : res_op->op_or_null (0),
554 : res_op->op_or_null (1),
555 : res_op->op_or_null (2),
556 : res_op->op_or_null (3),
557 : res_op->op_or_null (4));
558 : }
559 12114 : if (!res)
560 : {
561 1259 : if (gimple_in_ssa_p (cfun))
562 1259 : res = make_ssa_name (res_op->type);
563 : else
564 0 : res = create_tmp_reg (res_op->type);
565 : }
566 12114 : gimple_call_set_lhs (new_stmt, res);
567 12114 : gimple_seq_add_stmt_without_update (seq, new_stmt);
568 12114 : return res;
569 : }
570 : }
571 :
572 :
573 : /* Public API overloads follow for operation being tree_code or
574 : built_in_function and for one to three operands or arguments.
575 : They return NULL_TREE if nothing could be simplified or
576 : the resulting simplified value with parts pushed to SEQ.
577 : If SEQ is NULL then if the simplification needs to create
578 : new stmts it will fail. If VALUEIZE is non-NULL then all
579 : SSA names will be valueized using that hook prior to
580 : applying simplifications. */
581 :
582 : /* Unary ops. */
583 :
584 : tree
585 342988 : gimple_simplify (enum tree_code code, tree type,
586 : tree op0,
587 : gimple_seq *seq, tree (*valueize)(tree))
588 : {
589 342988 : if (constant_for_folding (op0))
590 : {
591 29858 : tree res = const_unop (code, type, op0);
592 29858 : if (res != NULL_TREE
593 29610 : && CONSTANT_CLASS_P (res))
594 : return res;
595 : }
596 :
597 313378 : gimple_match_op res_op;
598 313378 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
599 : return NULL_TREE;
600 11191 : return maybe_push_res_to_seq (&res_op, seq);
601 : }
602 :
603 : /* Binary ops. */
604 :
605 : tree
606 25355380 : gimple_simplify (enum tree_code code, tree type,
607 : tree op0, tree op1,
608 : gimple_seq *seq, tree (*valueize)(tree))
609 : {
610 25355380 : if (constant_for_folding (op0) && constant_for_folding (op1))
611 : {
612 1742301 : tree res = const_binop (code, type, op0, op1);
613 1742301 : if (res != NULL_TREE
614 1740936 : && CONSTANT_CLASS_P (res))
615 : return res;
616 : }
617 :
618 : /* Canonicalize operand order both for matching and fallback stmt
619 : generation. */
620 23614444 : if ((commutative_tree_code (code)
621 6794024 : || TREE_CODE_CLASS (code) == tcc_comparison)
622 30287308 : && tree_swap_operands_p (op0, op1))
623 : {
624 43179 : std::swap (op0, op1);
625 43179 : if (TREE_CODE_CLASS (code) == tcc_comparison)
626 3784 : code = swap_tree_comparison (code);
627 : }
628 :
629 23614444 : gimple_match_op res_op;
630 23614444 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
631 : return NULL_TREE;
632 2537065 : return maybe_push_res_to_seq (&res_op, seq);
633 : }
634 :
635 : /* Ternary ops. */
636 :
637 : tree
638 43727 : gimple_simplify (enum tree_code code, tree type,
639 : tree op0, tree op1, tree op2,
640 : gimple_seq *seq, tree (*valueize)(tree))
641 : {
642 44964 : if (constant_for_folding (op0) && constant_for_folding (op1)
643 44964 : && constant_for_folding (op2))
644 : {
645 1237 : tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
646 1237 : if (res != NULL_TREE
647 1237 : && CONSTANT_CLASS_P (res))
648 : return res;
649 : }
650 :
651 : /* Canonicalize operand order both for matching and fallback stmt
652 : generation. */
653 42490 : if (commutative_ternary_tree_code (code)
654 42490 : && tree_swap_operands_p (op0, op1))
655 : std::swap (op0, op1);
656 :
657 42490 : gimple_match_op res_op;
658 42490 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
659 : return NULL_TREE;
660 10765 : return maybe_push_res_to_seq (&res_op, seq);
661 : }
662 :
663 : /* Builtin or internal function with one argument. */
664 :
665 : tree
666 24997 : gimple_simplify (combined_fn fn, tree type,
667 : tree arg0,
668 : gimple_seq *seq, tree (*valueize)(tree))
669 : {
670 24997 : if (constant_for_folding (arg0))
671 : {
672 0 : tree res = fold_const_call (fn, type, arg0);
673 0 : if (res && CONSTANT_CLASS_P (res))
674 : return res;
675 : }
676 :
677 24997 : gimple_match_op res_op;
678 24997 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
679 : return NULL_TREE;
680 0 : return maybe_push_res_to_seq (&res_op, seq);
681 : }
682 :
683 : /* Builtin or internal function with two arguments. */
684 :
685 : tree
686 0 : gimple_simplify (combined_fn fn, tree type,
687 : tree arg0, tree arg1,
688 : gimple_seq *seq, tree (*valueize)(tree))
689 : {
690 0 : if (constant_for_folding (arg0)
691 0 : && constant_for_folding (arg1))
692 : {
693 0 : tree res = fold_const_call (fn, type, arg0, arg1);
694 0 : if (res && CONSTANT_CLASS_P (res))
695 : return res;
696 : }
697 :
698 0 : gimple_match_op res_op;
699 0 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
700 : return NULL_TREE;
701 0 : return maybe_push_res_to_seq (&res_op, seq);
702 : }
703 :
704 : /* Builtin or internal function with three arguments. */
705 :
706 : tree
707 0 : gimple_simplify (combined_fn fn, tree type,
708 : tree arg0, tree arg1, tree arg2,
709 : gimple_seq *seq, tree (*valueize)(tree))
710 : {
711 0 : if (constant_for_folding (arg0)
712 0 : && constant_for_folding (arg1)
713 0 : && constant_for_folding (arg2))
714 : {
715 0 : tree res = fold_const_call (fn, type, arg0, arg1, arg2);
716 0 : if (res && CONSTANT_CLASS_P (res))
717 : return res;
718 : }
719 :
720 0 : gimple_match_op res_op;
721 0 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
722 : return NULL_TREE;
723 0 : return maybe_push_res_to_seq (&res_op, seq);
724 : }
725 :
726 : /* Common subroutine of gimple_extract_op and gimple_simplify. Try to
727 : describe STMT in RES_OP, returning true on success. Before recording
728 : an operand, call:
729 :
730 : - VALUEIZE_OP for all top-level operand
731 :
732 : This routine takes a tree argument and returns a tree. */
733 :
734 : template<typename ValueizeOp>
735 : inline bool
736 1329713673 : gimple_extract (gimple *stmt, gimple_match_op *res_op,
737 : ValueizeOp valueize_op)
738 : {
739 1329713673 : switch (gimple_code (stmt))
740 : {
741 615715157 : case GIMPLE_ASSIGN:
742 : {
743 615715157 : enum tree_code code = gimple_assign_rhs_code (stmt);
744 615715157 : tree type = TREE_TYPE (gimple_assign_lhs (stmt));
745 615715157 : switch (gimple_assign_rhs_class (stmt))
746 : {
747 290159511 : case GIMPLE_SINGLE_RHS:
748 290159511 : if (code == REALPART_EXPR
749 : || code == IMAGPART_EXPR
750 290159511 : || code == VIEW_CONVERT_EXPR)
751 : {
752 7742205 : tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
753 : /* op0 needs to be a SSA name or an min invariant. */
754 7742205 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
755 : return false;
756 5550555 : res_op->set_op (code, type, valueize_op (op0));
757 5550555 : return true;
758 : }
759 282417306 : else if (code == BIT_FIELD_REF)
760 : {
761 1566880 : tree rhs1 = gimple_assign_rhs1 (stmt);
762 1566880 : tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
763 : /* op0 needs to be a SSA name or an min invariant. */
764 1566880 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
765 : return false;
766 905737 : res_op->set_op (code, type, op0,
767 905737 : TREE_OPERAND (rhs1, 1),
768 905737 : TREE_OPERAND (rhs1, 2),
769 905737 : REF_REVERSE_STORAGE_ORDER (rhs1));
770 905737 : return true;
771 : }
772 280850426 : else if (code == SSA_NAME)
773 : {
774 44704647 : tree op0 = gimple_assign_rhs1 (stmt);
775 44704647 : res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
776 44704647 : return true;
777 : }
778 : break;
779 82930059 : case GIMPLE_UNARY_RHS:
780 : {
781 82930059 : tree rhs1 = gimple_assign_rhs1 (stmt);
782 82930059 : res_op->set_op (code, type, valueize_op (rhs1));
783 82930059 : return true;
784 : }
785 241391421 : case GIMPLE_BINARY_RHS:
786 : {
787 241391421 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
788 241391421 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
789 241391421 : res_op->set_op (code, type, rhs1, rhs2);
790 241391421 : return true;
791 : }
792 1234166 : case GIMPLE_TERNARY_RHS:
793 : {
794 1234166 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
795 1234166 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
796 1234166 : tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
797 1234166 : res_op->set_op (code, type, rhs1, rhs2, rhs3);
798 1234166 : return true;
799 : }
800 0 : default:
801 0 : gcc_unreachable ();
802 : }
803 : break;
804 : }
805 :
806 69979969 : case GIMPLE_CALL:
807 : /* ??? This way we can't simplify calls with side-effects. */
808 69979969 : if (gimple_call_lhs (stmt) != NULL_TREE
809 36845419 : && gimple_call_num_args (stmt) >= 1
810 104800511 : && gimple_call_num_args (stmt) <= 7)
811 : {
812 : combined_fn cfn;
813 34735452 : if (gimple_call_internal_p (stmt))
814 3053792 : cfn = as_combined_fn (gimple_call_internal_fn (stmt));
815 : else
816 : {
817 31681660 : tree fn = gimple_call_fn (stmt);
818 31681660 : if (!fn)
819 : return false;
820 :
821 31681660 : fn = valueize_op (fn);
822 31681660 : if (TREE_CODE (fn) != ADDR_EXPR
823 31681660 : || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
824 : return false;
825 :
826 30173599 : tree decl = TREE_OPERAND (fn, 0);
827 30173599 : if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
828 30173599 : || !gimple_builtin_call_types_compatible_p (stmt, decl))
829 19970055 : return false;
830 :
831 10203544 : cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
832 : }
833 :
834 13257336 : unsigned int num_args = gimple_call_num_args (stmt);
835 13257336 : res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
836 43968681 : for (unsigned i = 0; i < num_args; ++i)
837 61263950 : res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
838 : return true;
839 : }
840 : break;
841 :
842 247922494 : case GIMPLE_COND:
843 : {
844 247922494 : tree lhs = valueize_op (gimple_cond_lhs (stmt));
845 247922494 : tree rhs = valueize_op (gimple_cond_rhs (stmt));
846 247922494 : res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
847 247922494 : return true;
848 : }
849 :
850 : default:
851 : break;
852 : }
853 :
854 : return false;
855 : }
856 :
857 : /* Try to describe STMT in RES_OP, returning true on success.
858 : For GIMPLE_CONDs, describe the condition that is being tested.
859 : For GIMPLE_ASSIGNs, describe the rhs of the assignment.
860 : For GIMPLE_CALLs, describe the call. */
861 :
862 : bool
863 1673889 : gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
864 : {
865 1673889 : auto nop = [](tree op) { return op; };
866 1673889 : return gimple_extract (stmt, res_op, nop);
867 : }
868 :
869 : /* The main STMT based simplification entry. It is used by the fold_stmt
870 : and the fold_stmt_to_constant APIs. */
871 :
872 : bool
873 1328039784 : gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
874 : tree (*valueize)(tree), tree (*top_valueize)(tree))
875 : {
876 1328039784 : bool valueized = false;
877 2505304370 : auto valueize_op = [&](tree op)
878 : {
879 1177264586 : return do_valueize (op, top_valueize, valueized);
880 1328039784 : };
881 :
882 1328039784 : if (!gimple_extract (stmt, res_op, valueize_op))
883 : return false;
884 :
885 636810329 : if (res_op->code.is_internal_fn ())
886 : {
887 3019822 : internal_fn ifn = internal_fn (res_op->code);
888 3019822 : if (try_conditional_simplification (ifn, res_op, seq, valueize))
889 : return true;
890 : }
891 :
892 636807389 : if (!res_op->reverse
893 636807389 : && res_op->num_ops
894 1273614778 : && res_op->resimplify (seq, valueize))
895 : return true;
896 :
897 570126238 : return valueized;
898 : }
899 :
900 : /* Helper that matches and simplifies the toplevel result from
901 : a gimple_simplify run (where we don't want to build
902 : a stmt in case it's used in in-place folding). Replaces
903 : RES_OP with a simplified and/or canonicalized result and
904 : returns whether any change was made. */
905 :
906 : static bool
907 153165557 : gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
908 : tree (*valueize)(tree))
909 : {
910 153165557 : if (constant_for_folding (res_op->ops[0]))
911 : {
912 13436856 : tree tem = NULL_TREE;
913 13436856 : if (res_op->code.is_tree_code ())
914 : {
915 12243161 : auto code = tree_code (res_op->code);
916 12243161 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
917 11389324 : && TREE_CODE_LENGTH (code) == 1)
918 11389324 : tem = const_unop (code, res_op->type, res_op->ops[0]);
919 : }
920 : else
921 1193695 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
922 : res_op->ops[0]);
923 12583019 : if (tem != NULL_TREE
924 11328964 : && CONSTANT_CLASS_P (tem))
925 : {
926 11328964 : if (TREE_OVERFLOW_P (tem))
927 2761 : tem = drop_tree_overflow (tem);
928 11328964 : res_op->set_value (tem);
929 11328964 : maybe_resimplify_conditional_op (seq, res_op, valueize);
930 11328964 : return true;
931 : }
932 : }
933 :
934 : /* Limit recursion, there are cases like PR80887 and others, for
935 : example when value-numbering presents us with unfolded expressions
936 : that we are really not prepared to handle without eventual
937 : oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
938 : itself as available expression. */
939 141836593 : static unsigned depth;
940 141836593 : if (depth > 10)
941 : {
942 2 : if (dump_file && (dump_flags & TDF_FOLDING))
943 0 : fprintf (dump_file, "Aborting expression simplification due to "
944 : "deep recursion\n");
945 2 : return false;
946 : }
947 :
948 141836591 : ++depth;
949 141836591 : gimple_match_op res_op2 (*res_op);
950 141836591 : if (gimple_simplify (&res_op2, seq, valueize,
951 : res_op->code, res_op->type, res_op->ops[0]))
952 : {
953 2622222 : --depth;
954 2622222 : *res_op = res_op2;
955 2622222 : return true;
956 : }
957 139214369 : --depth;
958 :
959 139214369 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
960 : return true;
961 :
962 : return false;
963 : }
964 :
965 : /* Helper that matches and simplifies the toplevel result from
966 : a gimple_simplify run (where we don't want to build
967 : a stmt in case it's used in in-place folding). Replaces
968 : RES_OP with a simplified and/or canonicalized result and
969 : returns whether any change was made. */
970 :
971 : static bool
972 516805552 : gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
973 : tree (*valueize)(tree))
974 : {
975 516805552 : if (constant_for_folding (res_op->ops[0])
976 516805552 : && constant_for_folding (res_op->ops[1]))
977 : {
978 22613023 : tree tem = NULL_TREE;
979 22613023 : if (res_op->code.is_tree_code ())
980 : {
981 22484155 : auto code = tree_code (res_op->code);
982 22484155 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
983 22484155 : && TREE_CODE_LENGTH (code) == 2)
984 22484155 : tem = const_binop (code, res_op->type,
985 : res_op->ops[0], res_op->ops[1]);
986 : }
987 : else
988 128868 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
989 : res_op->ops[0], res_op->ops[1]);
990 22613023 : if (tem != NULL_TREE
991 22435043 : && CONSTANT_CLASS_P (tem))
992 : {
993 22434997 : if (TREE_OVERFLOW_P (tem))
994 657 : tem = drop_tree_overflow (tem);
995 22434997 : res_op->set_value (tem);
996 22434997 : maybe_resimplify_conditional_op (seq, res_op, valueize);
997 22434997 : return true;
998 : }
999 : }
1000 :
1001 : /* Canonicalize operand order. */
1002 494370555 : bool canonicalized = false;
1003 494370555 : bool is_comparison
1004 494370555 : = (res_op->code.is_tree_code ()
1005 494370555 : && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison);
1006 233854738 : if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type))
1007 430622136 : && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
1008 : {
1009 8391250 : std::swap (res_op->ops[0], res_op->ops[1]);
1010 8391250 : if (is_comparison)
1011 3451478 : res_op->code = swap_tree_comparison (tree_code (res_op->code));
1012 : canonicalized = true;
1013 : }
1014 :
1015 : /* Limit recursion, see gimple_resimplify1. */
1016 494370555 : static unsigned depth;
1017 494370555 : if (depth > 10)
1018 : {
1019 40709 : if (dump_file && (dump_flags & TDF_FOLDING))
1020 0 : fprintf (dump_file, "Aborting expression simplification due to "
1021 : "deep recursion\n");
1022 40709 : return false;
1023 : }
1024 :
1025 494329846 : ++depth;
1026 494329846 : gimple_match_op res_op2 (*res_op);
1027 494329846 : if (gimple_simplify (&res_op2, seq, valueize,
1028 : res_op->code, res_op->type,
1029 : res_op->ops[0], res_op->ops[1]))
1030 : {
1031 38753055 : --depth;
1032 38753055 : *res_op = res_op2;
1033 38753055 : return true;
1034 : }
1035 455576791 : --depth;
1036 :
1037 455576791 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1038 : return true;
1039 :
1040 : return canonicalized;
1041 : }
1042 :
1043 : /* Helper that matches and simplifies the toplevel result from
1044 : a gimple_simplify run (where we don't want to build
1045 : a stmt in case it's used in in-place folding). Replaces
1046 : RES_OP with a simplified and/or canonicalized result and
1047 : returns whether any change was made. */
1048 :
1049 : static bool
1050 6915624 : gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
1051 : tree (*valueize)(tree))
1052 : {
1053 6915624 : if (constant_for_folding (res_op->ops[0])
1054 800467 : && constant_for_folding (res_op->ops[1])
1055 7511453 : && constant_for_folding (res_op->ops[2]))
1056 : {
1057 81373 : tree tem = NULL_TREE;
1058 81373 : if (res_op->code.is_tree_code ())
1059 : {
1060 43520 : auto code = tree_code (res_op->code);
1061 43520 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
1062 43520 : && TREE_CODE_LENGTH (code) == 3)
1063 43520 : tem = fold_ternary/*_to_constant*/ (code, res_op->type,
1064 : res_op->ops[0], res_op->ops[1],
1065 : res_op->ops[2]);
1066 : }
1067 : else
1068 37853 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
1069 : res_op->ops[0], res_op->ops[1], res_op->ops[2]);
1070 81373 : if (tem != NULL_TREE
1071 43461 : && CONSTANT_CLASS_P (tem))
1072 : {
1073 43327 : if (TREE_OVERFLOW_P (tem))
1074 4 : tem = drop_tree_overflow (tem);
1075 43327 : res_op->set_value (tem);
1076 43327 : maybe_resimplify_conditional_op (seq, res_op, valueize);
1077 43327 : return true;
1078 : }
1079 : }
1080 :
1081 : /* Canonicalize operand order. */
1082 6872297 : bool canonicalized = false;
1083 6872297 : int argno = first_commutative_argument (res_op->code, res_op->type);
1084 6872297 : if (argno >= 0
1085 6872297 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1086 : {
1087 1164 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1088 1164 : canonicalized = true;
1089 : }
1090 :
1091 : /* Limit recursion, see gimple_resimplify1. */
1092 6872297 : static unsigned depth;
1093 6872297 : if (depth > 10)
1094 : {
1095 33 : if (dump_file && (dump_flags & TDF_FOLDING))
1096 0 : fprintf (dump_file, "Aborting expression simplification due to "
1097 : "deep recursion\n");
1098 33 : return false;
1099 : }
1100 :
1101 6872264 : ++depth;
1102 6872264 : gimple_match_op res_op2 (*res_op);
1103 6872264 : if (gimple_simplify (&res_op2, seq, valueize,
1104 : res_op->code, res_op->type,
1105 : res_op->ops[0], res_op->ops[1], res_op->ops[2]))
1106 : {
1107 432734 : --depth;
1108 432734 : *res_op = res_op2;
1109 432734 : return true;
1110 : }
1111 6439530 : --depth;
1112 :
1113 6439530 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1114 : return true;
1115 :
1116 : return canonicalized;
1117 : }
1118 :
1119 : /* Helper that matches and simplifies the toplevel result from
1120 : a gimple_simplify run (where we don't want to build
1121 : a stmt in case it's used in in-place folding). Replaces
1122 : RES_OP with a simplified and/or canonicalized result and
1123 : returns whether any change was made. */
1124 :
1125 : static bool
1126 245440 : gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
1127 : tree (*valueize)(tree))
1128 : {
1129 : /* No constant folding is defined for four-operand functions. */
1130 :
1131 : /* Canonicalize operand order. */
1132 245440 : bool canonicalized = false;
1133 245440 : int argno = first_commutative_argument (res_op->code, res_op->type);
1134 245440 : if (argno >= 0
1135 245440 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1136 : {
1137 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1138 0 : canonicalized = true;
1139 : }
1140 :
1141 : /* Limit recursion, see gimple_resimplify1. */
1142 245440 : static unsigned depth;
1143 245440 : if (depth > 10)
1144 : {
1145 0 : if (dump_file && (dump_flags & TDF_FOLDING))
1146 0 : fprintf (dump_file, "Aborting expression simplification due to "
1147 : "deep recursion\n");
1148 0 : return false;
1149 : }
1150 :
1151 245440 : ++depth;
1152 245440 : gimple_match_op res_op2 (*res_op);
1153 245440 : if (gimple_simplify (&res_op2, seq, valueize,
1154 : res_op->code, res_op->type,
1155 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1156 : res_op->ops[3]))
1157 : {
1158 0 : --depth;
1159 0 : *res_op = res_op2;
1160 0 : return true;
1161 : }
1162 245440 : --depth;
1163 :
1164 245440 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1165 : return true;
1166 :
1167 : return canonicalized;
1168 : }
1169 :
1170 : /* Helper that matches and simplifies the toplevel result from
1171 : a gimple_simplify run (where we don't want to build
1172 : a stmt in case it's used in in-place folding). Replaces
1173 : RES_OP with a simplified and/or canonicalized result and
1174 : returns whether any change was made. */
1175 :
1176 : static bool
1177 24732 : gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
1178 : tree (*valueize)(tree))
1179 : {
1180 : /* No constant folding is defined for five-operand functions. */
1181 :
1182 : /* Canonicalize operand order. */
1183 24732 : bool canonicalized = false;
1184 24732 : int argno = first_commutative_argument (res_op->code, res_op->type);
1185 24732 : if (argno >= 0
1186 24732 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1187 : {
1188 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1189 0 : canonicalized = true;
1190 : }
1191 :
1192 24732 : gimple_match_op res_op2 (*res_op);
1193 24732 : if (gimple_simplify (&res_op2, seq, valueize,
1194 : res_op->code, res_op->type,
1195 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1196 : res_op->ops[3], res_op->ops[4]))
1197 : {
1198 0 : *res_op = res_op2;
1199 0 : return true;
1200 : }
1201 :
1202 24732 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1203 : return true;
1204 :
1205 : return canonicalized;
1206 : }
1207 :
1208 : /* Helper that matches and simplifies the toplevel result from
1209 : a gimple_simplify run (where we don't want to build
1210 : a stmt in case it's used in in-place folding). Replaces
1211 : RES_OP with a simplified and/or canonicalized result and
1212 : returns whether any change was made. */
1213 :
1214 : static bool
1215 603093 : gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
1216 : tree (*valueize)(tree))
1217 : {
1218 : /* No constant folding is defined for six-operand functions. */
1219 :
1220 : /* Canonicalize operand order. */
1221 603093 : bool canonicalized = false;
1222 603093 : int argno = first_commutative_argument (res_op->code, res_op->type);
1223 603093 : if (argno >= 0
1224 603093 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1225 : {
1226 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1227 0 : canonicalized = true;
1228 : }
1229 :
1230 603093 : gimple_match_op res_op2 (*res_op);
1231 603093 : if (gimple_simplify (&res_op2, seq, valueize,
1232 : res_op->code, res_op->type,
1233 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1234 : res_op->ops[3], res_op->ops[4], res_op->ops[5]))
1235 : {
1236 0 : *res_op = res_op2;
1237 0 : return true;
1238 : }
1239 :
1240 603093 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1241 : return true;
1242 :
1243 : return canonicalized;
1244 : }
1245 :
1246 : /* Helper that matches and simplifies the toplevel result from
1247 : a gimple_simplify run (where we don't want to build
1248 : a stmt in case it's used in in-place folding). Replaces
1249 : RES_OP with a simplified and/or canonicalized result and
1250 : returns whether any change was made. */
1251 :
1252 : static bool
1253 83879 : gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
1254 : tree (*valueize)(tree))
1255 : {
1256 : /* No constant folding is defined for seven-operand functions. */
1257 :
1258 : /* Canonicalize operand order. */
1259 83879 : bool canonicalized = false;
1260 83879 : int argno = first_commutative_argument (res_op->code, res_op->type);
1261 83879 : if (argno >= 0
1262 83879 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1263 : {
1264 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1265 0 : canonicalized = true;
1266 : }
1267 :
1268 83879 : gimple_match_op res_op2 (*res_op);
1269 83879 : if (gimple_simplify (&res_op2, seq, valueize,
1270 : res_op->code, res_op->type,
1271 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1272 : res_op->ops[3], res_op->ops[4], res_op->ops[5],
1273 : res_op->ops[6]))
1274 : {
1275 0 : *res_op = res_op2;
1276 0 : return true;
1277 : }
1278 :
1279 83879 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1280 : return true;
1281 :
1282 : return canonicalized;
1283 : }
1284 :
1285 : /* Return a canonical form for CODE when operating on TYPE. The idea
1286 : is to remove redundant ways of representing the same operation so
1287 : that code_helpers can be hashed and compared for equality.
1288 :
1289 : The only current canonicalization is to replace built-in functions
1290 : with internal functions, in cases where internal-fn.def defines
1291 : such an internal function.
1292 :
1293 : Note that the new code_helper cannot necessarily be used in place of
1294 : the original code_helper. For example, the new code_helper might be
1295 : an internal function that the target does not support. */
1296 :
1297 : code_helper
1298 92780 : canonicalize_code (code_helper code, tree type)
1299 : {
1300 92780 : if (code.is_fn_code ())
1301 4000 : return associated_internal_fn (combined_fn (code), type);
1302 88780 : return code;
1303 : }
1304 :
1305 : /* Return true if CODE is a binary operation and if CODE is commutative when
1306 : operating on type TYPE. */
1307 :
1308 : bool
1309 233897390 : commutative_binary_op_p (code_helper code, tree type)
1310 : {
1311 233897390 : if (code.is_tree_code ())
1312 228017489 : return commutative_tree_code (tree_code (code));
1313 5879901 : auto cfn = combined_fn (code);
1314 5879901 : return commutative_binary_fn_p (associated_internal_fn (cfn, type));
1315 : }
1316 :
1317 : /* Return true if CODE represents a ternary operation and if the first two
1318 : operands are commutative when CODE is operating on TYPE. */
1319 :
1320 : bool
1321 0 : commutative_ternary_op_p (code_helper code, tree type)
1322 : {
1323 0 : if (code.is_tree_code ())
1324 0 : return commutative_ternary_tree_code (tree_code (code));
1325 0 : auto cfn = combined_fn (code);
1326 0 : return commutative_ternary_fn_p (associated_internal_fn (cfn, type));
1327 : }
1328 :
1329 : /* If CODE is commutative in two consecutive operands, return the
1330 : index of the first, otherwise return -1. */
1331 :
1332 : int
1333 7830552 : first_commutative_argument (code_helper code, tree type)
1334 : {
1335 7830552 : if (code.is_tree_code ())
1336 : {
1337 3330444 : auto tcode = tree_code (code);
1338 3330444 : if (commutative_tree_code (tcode)
1339 3330444 : || commutative_ternary_tree_code (tcode))
1340 2996 : return 0;
1341 : return -1;
1342 : }
1343 4500108 : auto cfn = combined_fn (code);
1344 4500108 : return first_commutative_argument (associated_internal_fn (cfn, type));
1345 : }
1346 :
1347 : /* Return true if CODE is a binary operation that is associative when
1348 : operating on type TYPE. */
1349 :
1350 : bool
1351 42500 : associative_binary_op_p (code_helper code, tree type)
1352 : {
1353 42500 : if (code.is_tree_code ())
1354 42448 : return associative_tree_code (tree_code (code));
1355 52 : auto cfn = combined_fn (code);
1356 52 : return associative_binary_fn_p (associated_internal_fn (cfn, type));
1357 : }
1358 :
1359 : /* Return true if the target directly supports operation CODE on type TYPE.
1360 : QUERY_TYPE acts as for optab_for_tree_code. */
1361 :
1362 : bool
1363 262590 : directly_supported_p (code_helper code, tree type, optab_subtype query_type)
1364 : {
1365 262590 : if (code.is_tree_code ())
1366 : {
1367 261017 : direct_optab optab = optab_for_tree_code (tree_code (code), type,
1368 : query_type);
1369 261017 : return (optab != unknown_optab
1370 261017 : && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing);
1371 : }
1372 1573 : gcc_assert (query_type == optab_default
1373 : || (query_type == optab_vector && VECTOR_TYPE_P (type))
1374 : || (query_type == optab_scalar && !VECTOR_TYPE_P (type)));
1375 1573 : internal_fn ifn = associated_internal_fn (combined_fn (code), type);
1376 1573 : return (direct_internal_fn_p (ifn)
1377 1573 : && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
1378 : }
1379 :
1380 : /* As above, overloading the function for conversion-type optabs. */
1381 : bool
1382 2612 : directly_supported_p (code_helper code, tree otype, tree itype,
1383 : optab_subtype query_type)
1384 : {
1385 2612 : if (code.is_tree_code ())
1386 : {
1387 2612 : convert_optab optab = optab_for_tree_code (tree_code (code), itype,
1388 : query_type);
1389 2612 : return (optab != unknown_optab
1390 5224 : && convert_optab_handler (optab, TYPE_MODE (otype),
1391 2612 : TYPE_MODE (itype)) != CODE_FOR_nothing);
1392 : }
1393 0 : gcc_assert (query_type == optab_default
1394 : || (query_type == optab_vector && VECTOR_TYPE_P (itype))
1395 : || (query_type == optab_scalar && !VECTOR_TYPE_P (itype)));
1396 0 : internal_fn ifn = associated_internal_fn (combined_fn (code), itype);
1397 0 : return (direct_internal_fn_p (ifn)
1398 0 : && direct_internal_fn_supported_p (ifn, tree_pair (otype, itype),
1399 : OPTIMIZE_FOR_SPEED));
1400 : }
1401 :
1402 :
1403 : /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn
1404 : for a code_helper CODE operating on type TYPE. */
1405 :
1406 : internal_fn
1407 4382 : get_conditional_internal_fn (code_helper code, tree type)
1408 : {
1409 4382 : if (code.is_tree_code ())
1410 4382 : return get_conditional_internal_fn (tree_code (code));
1411 0 : auto cfn = combined_fn (code);
1412 0 : return get_conditional_internal_fn (associated_internal_fn (cfn, type));
1413 : }
|