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 679283706 : gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
107 : {
108 679283706 : switch (num_ops)
109 : {
110 153775107 : case 1:
111 153775107 : return gimple_resimplify1 (seq, this, valueize);
112 517288406 : case 2:
113 517288406 : return gimple_resimplify2 (seq, this, valueize);
114 7259848 : case 3:
115 7259848 : return gimple_resimplify3 (seq, this, valueize);
116 248556 : case 4:
117 248556 : return gimple_resimplify4 (seq, this, valueize);
118 24732 : case 5:
119 24732 : return gimple_resimplify5 (seq, this, valueize);
120 603178 : case 6:
121 603178 : 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 591493 : gimple_match_op::operands_occurs_in_abnormal_phi() const
133 : {
134 1651314 : for (unsigned int i = 0; i < num_ops; i++)
135 : {
136 1059821 : if (TREE_CODE (ops[i]) == SSA_NAME
137 1059821 : && 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 736796649 : constant_for_folding (tree t)
148 : {
149 736796649 : return (CONSTANT_CLASS_P (t)
150 : /* The following is only interesting to string builtins. */
151 736796649 : || (TREE_CODE (t) == ADDR_EXPR
152 13661294 : && 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 1179314705 : do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
210 : {
211 1179314705 : if (valueize && TREE_CODE (op) == SSA_NAME)
212 : {
213 744040276 : tree tem = valueize (op);
214 744040276 : if (tem && tem != op)
215 : {
216 51976011 : op = tem;
217 51976011 : valueized = true;
218 : }
219 : }
220 1179314705 : 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 2907506 : maybe_build_generic_op (gimple_match_op *res_op)
228 : {
229 2907506 : tree_code code = (tree_code) res_op->code;
230 2907506 : tree val;
231 2907506 : switch (code)
232 : {
233 10251 : case REALPART_EXPR:
234 10251 : case IMAGPART_EXPR:
235 10251 : case VIEW_CONVERT_EXPR:
236 10251 : val = build1 (code, res_op->type, res_op->ops[0]);
237 10251 : res_op->set_value (val);
238 10251 : break;
239 86781 : case BIT_FIELD_REF:
240 86781 : val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
241 : res_op->ops[2]);
242 86781 : REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
243 86781 : res_op->set_value (val);
244 86781 : break;
245 2907506 : default:;
246 : }
247 2907506 : }
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 637415911 : maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
304 : tree (*valueize) (tree))
305 : {
306 637415911 : 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 3060047 : try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
401 : gimple_seq *seq, tree (*valueize) (tree))
402 : {
403 3060047 : code_helper op;
404 3060047 : tree_code code = conditional_internal_fn_code (ifn);
405 3060047 : int len_index = internal_fn_len_index (ifn);
406 3060047 : if (code != ERROR_MARK)
407 11993 : op = code;
408 : else
409 : {
410 3048054 : ifn = get_unconditional_internal_fn (ifn);
411 3048054 : 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 701255738 : do_valueize (tree (*valueize)(tree), tree op)
455 : {
456 701255738 : if (valueize && TREE_CODE (op) == SSA_NAME)
457 : {
458 520664106 : tree tem = valueize (op);
459 520664106 : 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 12477016 : maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
472 : {
473 12477016 : tree *ops = res_op->ops;
474 12477016 : 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 12477016 : if (res_op->cond.cond)
480 : return NULL_TREE;
481 :
482 12476617 : if (res_op->code.is_tree_code ())
483 : {
484 12460960 : if (!res
485 12460960 : && gimple_simplified_result_is_gimple_val (res_op))
486 6935300 : return ops[0];
487 5525660 : if (mprts_hook)
488 : {
489 2121217 : tree tem = mprts_hook (res_op);
490 2121217 : if (tem)
491 : return tem;
492 : }
493 : }
494 :
495 5487321 : if (!seq)
496 : return NULL_TREE;
497 :
498 : /* Play safe and do not allow abnormals to be mentioned in
499 : newly created statements. */
500 2133061 : for (unsigned int i = 0; i < num_ops; ++i)
501 1356726 : if (TREE_CODE (ops[i]) == SSA_NAME
502 1356726 : && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
503 : return NULL_TREE;
504 :
505 776335 : if (res_op->code.is_tree_code ())
506 : {
507 763506 : auto code = tree_code (res_op->code);
508 763506 : if (!res)
509 : {
510 682724 : if (gimple_in_ssa_p (cfun))
511 681746 : res = make_ssa_name (res_op->type);
512 : else
513 978 : res = create_tmp_reg (res_op->type);
514 : }
515 763506 : maybe_build_generic_op (res_op);
516 1945528 : 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 763506 : gimple_seq_add_stmt_without_update (seq, new_stmt);
521 763506 : return res;
522 : }
523 : else
524 : {
525 12829 : gcc_assert (num_ops != 0);
526 12829 : auto fn = combined_fn (res_op->code);
527 12829 : gcall *new_stmt = NULL;
528 12829 : 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 4596 : tree decl = builtin_decl_implicit (as_builtin_fn (fn));
545 4596 : if (!decl)
546 : return NULL;
547 :
548 : /* We can't and should not emit calls to non-const functions. */
549 4592 : if (!(flags_from_decl_or_type (decl) & ECF_CONST))
550 : return NULL;
551 :
552 8081 : 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 12112 : 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 12112 : gimple_call_set_lhs (new_stmt, res);
567 12112 : gimple_seq_add_stmt_without_update (seq, new_stmt);
568 12112 : 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 342274 : gimple_simplify (enum tree_code code, tree type,
586 : tree op0,
587 : gimple_seq *seq, tree (*valueize)(tree))
588 : {
589 342274 : if (constant_for_folding (op0))
590 : {
591 29888 : tree res = const_unop (code, type, op0);
592 29888 : if (res != NULL_TREE
593 29640 : && CONSTANT_CLASS_P (res))
594 : return res;
595 : }
596 :
597 312634 : gimple_match_op res_op;
598 312634 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
599 : return NULL_TREE;
600 11163 : return maybe_push_res_to_seq (&res_op, seq);
601 : }
602 :
603 : /* Binary ops. */
604 :
605 : tree
606 25358070 : gimple_simplify (enum tree_code code, tree type,
607 : tree op0, tree op1,
608 : gimple_seq *seq, tree (*valueize)(tree))
609 : {
610 25358070 : if (constant_for_folding (op0) && constant_for_folding (op1))
611 : {
612 1750670 : tree res = const_binop (code, type, op0, op1);
613 1750670 : if (res != NULL_TREE
614 1749102 : && CONSTANT_CLASS_P (res))
615 : return res;
616 : }
617 :
618 : /* Canonicalize operand order both for matching and fallback stmt
619 : generation. */
620 23608968 : if ((commutative_tree_code (code)
621 6771534 : || TREE_CODE_CLASS (code) == tcc_comparison)
622 30258659 : && tree_swap_operands_p (op0, op1))
623 : {
624 43496 : std::swap (op0, op1);
625 43496 : if (TREE_CODE_CLASS (code) == tcc_comparison)
626 3986 : code = swap_tree_comparison (code);
627 : }
628 :
629 23608968 : gimple_match_op res_op;
630 23608968 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
631 : return NULL_TREE;
632 2541752 : return maybe_push_res_to_seq (&res_op, seq);
633 : }
634 :
635 : /* Ternary ops. */
636 :
637 : tree
638 44445 : gimple_simplify (enum tree_code code, tree type,
639 : tree op0, tree op1, tree op2,
640 : gimple_seq *seq, tree (*valueize)(tree))
641 : {
642 45682 : if (constant_for_folding (op0) && constant_for_folding (op1)
643 45682 : && 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 43208 : if (commutative_ternary_tree_code (code)
654 43208 : && tree_swap_operands_p (op0, op1))
655 : std::swap (op0, op1);
656 :
657 43208 : gimple_match_op res_op;
658 43208 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
659 : return NULL_TREE;
660 10978 : return maybe_push_res_to_seq (&res_op, seq);
661 : }
662 :
663 : /* Builtin or internal function with one argument. */
664 :
665 : tree
666 25019 : gimple_simplify (combined_fn fn, tree type,
667 : tree arg0,
668 : gimple_seq *seq, tree (*valueize)(tree))
669 : {
670 25019 : 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 25019 : gimple_match_op res_op;
678 25019 : 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 1331117721 : gimple_extract (gimple *stmt, gimple_match_op *res_op,
737 : ValueizeOp valueize_op)
738 : {
739 1331117721 : switch (gimple_code (stmt))
740 : {
741 616823405 : case GIMPLE_ASSIGN:
742 : {
743 616823405 : enum tree_code code = gimple_assign_rhs_code (stmt);
744 616823405 : tree type = TREE_TYPE (gimple_assign_lhs (stmt));
745 616823405 : switch (gimple_assign_rhs_class (stmt))
746 : {
747 290618803 : case GIMPLE_SINGLE_RHS:
748 290618803 : if (code == REALPART_EXPR
749 : || code == IMAGPART_EXPR
750 290618803 : || code == VIEW_CONVERT_EXPR)
751 : {
752 7825941 : tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
753 : /* op0 needs to be a SSA name or an min invariant. */
754 7825941 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
755 : return false;
756 5632011 : res_op->set_op (code, type, valueize_op (op0));
757 5632011 : return true;
758 : }
759 282792862 : else if (code == BIT_FIELD_REF)
760 : {
761 1886413 : tree rhs1 = gimple_assign_rhs1 (stmt);
762 1886413 : tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
763 : /* op0 needs to be a SSA name or an min invariant. */
764 1886413 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
765 : return false;
766 1160662 : res_op->set_op (code, type, op0,
767 1160662 : TREE_OPERAND (rhs1, 1),
768 1160662 : TREE_OPERAND (rhs1, 2),
769 1160662 : REF_REVERSE_STORAGE_ORDER (rhs1));
770 1160662 : return true;
771 : }
772 280906449 : else if (code == SSA_NAME)
773 : {
774 44731710 : tree op0 = gimple_assign_rhs1 (stmt);
775 44731710 : res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
776 44731710 : return true;
777 : }
778 : break;
779 83252617 : case GIMPLE_UNARY_RHS:
780 : {
781 83252617 : tree rhs1 = gimple_assign_rhs1 (stmt);
782 83252617 : res_op->set_op (code, type, valueize_op (rhs1));
783 83252617 : return true;
784 : }
785 241646133 : case GIMPLE_BINARY_RHS:
786 : {
787 241646133 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
788 241646133 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
789 241646133 : res_op->set_op (code, type, rhs1, rhs2);
790 241646133 : return true;
791 : }
792 1305852 : case GIMPLE_TERNARY_RHS:
793 : {
794 1305852 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
795 1305852 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
796 1305852 : tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
797 1305852 : res_op->set_op (code, type, rhs1, rhs2, rhs3);
798 1305852 : return true;
799 : }
800 0 : default:
801 0 : gcc_unreachable ();
802 : }
803 : break;
804 : }
805 :
806 70052618 : case GIMPLE_CALL:
807 : /* ??? This way we can't simplify calls with side-effects. */
808 70052618 : if (gimple_call_lhs (stmt) != NULL_TREE
809 37021150 : && gimple_call_num_args (stmt) >= 1
810 105051563 : && gimple_call_num_args (stmt) <= 7)
811 : {
812 : combined_fn cfn;
813 34913885 : if (gimple_call_internal_p (stmt))
814 3094017 : cfn = as_combined_fn (gimple_call_internal_fn (stmt));
815 : else
816 : {
817 31819868 : tree fn = gimple_call_fn (stmt);
818 31819868 : if (!fn)
819 : return false;
820 :
821 31819868 : fn = valueize_op (fn);
822 31819868 : if (TREE_CODE (fn) != ADDR_EXPR
823 31819868 : || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
824 : return false;
825 :
826 30326473 : tree decl = TREE_OPERAND (fn, 0);
827 30326473 : if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
828 30326473 : || !gimple_builtin_call_types_compatible_p (stmt, decl))
829 20004412 : return false;
830 :
831 10322061 : cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
832 : }
833 :
834 13416078 : unsigned int num_args = gimple_call_num_args (stmt);
835 13416078 : res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
836 44329340 : for (unsigned i = 0; i < num_args; ++i)
837 61667751 : res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
838 : return true;
839 : }
840 : break;
841 :
842 248041395 : case GIMPLE_COND:
843 : {
844 248041395 : tree lhs = valueize_op (gimple_cond_lhs (stmt));
845 248041395 : tree rhs = valueize_op (gimple_cond_rhs (stmt));
846 248041395 : res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
847 248041395 : 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 1676170 : gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
864 : {
865 1676170 : auto nop = [](tree op) { return op; };
866 1676170 : 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 1329441551 : gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
874 : tree (*valueize)(tree), tree (*top_valueize)(tree))
875 : {
876 1329441551 : bool valueized = false;
877 2508756256 : auto valueize_op = [&](tree op)
878 : {
879 1179314705 : return do_valueize (op, top_valueize, valueized);
880 1329441551 : };
881 :
882 1329441551 : if (!gimple_extract (stmt, res_op, valueize_op))
883 : return false;
884 :
885 638098627 : if (res_op->code.is_internal_fn ())
886 : {
887 3060047 : internal_fn ifn = internal_fn (res_op->code);
888 3060047 : if (try_conditional_simplification (ifn, res_op, seq, valueize))
889 : return true;
890 : }
891 :
892 638095687 : if (!res_op->reverse
893 638095687 : && res_op->num_ops
894 1276191374 : && res_op->resimplify (seq, valueize))
895 : return true;
896 :
897 571347492 : 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 153775107 : gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
908 : tree (*valueize)(tree))
909 : {
910 153775107 : if (constant_for_folding (res_op->ops[0]))
911 : {
912 13470894 : tree tem = NULL_TREE;
913 13470894 : if (res_op->code.is_tree_code ())
914 : {
915 12271920 : auto code = tree_code (res_op->code);
916 12271920 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
917 11420201 : && TREE_CODE_LENGTH (code) == 1)
918 11420201 : tem = const_unop (code, res_op->type, res_op->ops[0]);
919 : }
920 : else
921 1198974 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
922 : res_op->ops[0]);
923 12619175 : if (tem != NULL_TREE
924 11358179 : && CONSTANT_CLASS_P (tem))
925 : {
926 11358179 : if (TREE_OVERFLOW_P (tem))
927 2761 : tem = drop_tree_overflow (tem);
928 11358179 : res_op->set_value (tem);
929 11358179 : maybe_resimplify_conditional_op (seq, res_op, valueize);
930 11358179 : 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 142416928 : static unsigned depth;
940 142416928 : 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 142416926 : ++depth;
949 142416926 : gimple_match_op res_op2 (*res_op);
950 142416926 : if (gimple_simplify (&res_op2, seq, valueize,
951 : res_op->code, res_op->type, res_op->ops[0]))
952 : {
953 2619755 : --depth;
954 2619755 : *res_op = res_op2;
955 2619755 : return true;
956 : }
957 139797171 : --depth;
958 :
959 139797171 : 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 517300399 : gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
973 : tree (*valueize)(tree))
974 : {
975 517300399 : if (constant_for_folding (res_op->ops[0])
976 517300399 : && constant_for_folding (res_op->ops[1]))
977 : {
978 22627893 : tree tem = NULL_TREE;
979 22627893 : if (res_op->code.is_tree_code ())
980 : {
981 22496273 : auto code = tree_code (res_op->code);
982 22496273 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
983 22496273 : && TREE_CODE_LENGTH (code) == 2)
984 22496273 : tem = const_binop (code, res_op->type,
985 : res_op->ops[0], res_op->ops[1]);
986 : }
987 : else
988 131620 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
989 : res_op->ops[0], res_op->ops[1]);
990 22627893 : if (tem != NULL_TREE
991 22446589 : && CONSTANT_CLASS_P (tem))
992 : {
993 22446543 : if (TREE_OVERFLOW_P (tem))
994 657 : tem = drop_tree_overflow (tem);
995 22446543 : res_op->set_value (tem);
996 22446543 : maybe_resimplify_conditional_op (seq, res_op, valueize);
997 22446543 : return true;
998 : }
999 : }
1000 :
1001 : /* Canonicalize operand order. */
1002 494853856 : bool canonicalized = false;
1003 494853856 : bool is_comparison
1004 494853856 : = (res_op->code.is_tree_code ()
1005 494853856 : && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison);
1006 234062824 : if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type))
1007 431105825 : && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
1008 : {
1009 8401778 : std::swap (res_op->ops[0], res_op->ops[1]);
1010 8401778 : if (is_comparison)
1011 3458793 : res_op->code = swap_tree_comparison (tree_code (res_op->code));
1012 : canonicalized = true;
1013 : }
1014 :
1015 : /* Limit recursion, see gimple_resimplify1. */
1016 494853856 : static unsigned depth;
1017 494853856 : 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 494813147 : ++depth;
1026 494813147 : gimple_match_op res_op2 (*res_op);
1027 494813147 : 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 38787523 : --depth;
1032 38787523 : *res_op = res_op2;
1033 38787523 : return true;
1034 : }
1035 456025624 : --depth;
1036 :
1037 456025624 : 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 7262251 : gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
1051 : tree (*valueize)(tree))
1052 : {
1053 7262251 : if (constant_for_folding (res_op->ops[0])
1054 835410 : && constant_for_folding (res_op->ops[1])
1055 7892218 : && constant_for_folding (res_op->ops[2]))
1056 : {
1057 87328 : tree tem = NULL_TREE;
1058 87328 : if (res_op->code.is_tree_code ())
1059 : {
1060 49408 : auto code = tree_code (res_op->code);
1061 49408 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
1062 49408 : && TREE_CODE_LENGTH (code) == 3)
1063 49408 : 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 37920 : 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 87328 : if (tem != NULL_TREE
1071 49367 : && CONSTANT_CLASS_P (tem))
1072 : {
1073 49221 : if (TREE_OVERFLOW_P (tem))
1074 4 : tem = drop_tree_overflow (tem);
1075 49221 : res_op->set_value (tem);
1076 49221 : maybe_resimplify_conditional_op (seq, res_op, valueize);
1077 49221 : return true;
1078 : }
1079 : }
1080 :
1081 : /* Canonicalize operand order. */
1082 7213030 : bool canonicalized = false;
1083 7213030 : int argno = first_commutative_argument (res_op->code, res_op->type);
1084 7213030 : if (argno >= 0
1085 7213030 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1086 : {
1087 1166 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1088 1166 : canonicalized = true;
1089 : }
1090 :
1091 : /* Limit recursion, see gimple_resimplify1. */
1092 7213030 : static unsigned depth;
1093 7213030 : 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 7212997 : ++depth;
1102 7212997 : gimple_match_op res_op2 (*res_op);
1103 7212997 : 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 437109 : --depth;
1108 437109 : *res_op = res_op2;
1109 437109 : return true;
1110 : }
1111 6775888 : --depth;
1112 :
1113 6775888 : 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 248556 : 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 248556 : bool canonicalized = false;
1133 248556 : int argno = first_commutative_argument (res_op->code, res_op->type);
1134 248556 : if (argno >= 0
1135 248556 : && 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 248556 : static unsigned depth;
1143 248556 : 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 248556 : ++depth;
1152 248556 : gimple_match_op res_op2 (*res_op);
1153 248556 : 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 248556 : --depth;
1163 :
1164 248556 : 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 603178 : 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 603178 : bool canonicalized = false;
1222 603178 : int argno = first_commutative_argument (res_op->code, res_op->type);
1223 603178 : if (argno >= 0
1224 603178 : && 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 603178 : gimple_match_op res_op2 (*res_op);
1231 603178 : 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 603178 : 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 92842 : canonicalize_code (code_helper code, tree type)
1299 : {
1300 92842 : if (code.is_fn_code ())
1301 4000 : return associated_internal_fn (combined_fn (code), type);
1302 88842 : 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 234105452 : commutative_binary_op_p (code_helper code, tree type)
1310 : {
1311 234105452 : if (code.is_tree_code ())
1312 228210886 : return commutative_tree_code (tree_code (code));
1313 5894566 : auto cfn = combined_fn (code);
1314 5894566 : 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 8174486 : first_commutative_argument (code_helper code, tree type)
1334 : {
1335 8174486 : if (code.is_tree_code ())
1336 : {
1337 3661761 : auto tcode = tree_code (code);
1338 3661761 : if (commutative_tree_code (tcode)
1339 3661761 : || commutative_ternary_tree_code (tcode))
1340 2996 : return 0;
1341 : return -1;
1342 : }
1343 4512725 : auto cfn = combined_fn (code);
1344 4512725 : 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 42476 : associative_binary_op_p (code_helper code, tree type)
1352 : {
1353 42476 : if (code.is_tree_code ())
1354 42424 : 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 263564 : directly_supported_p (code_helper code, tree type, optab_subtype query_type)
1364 : {
1365 263564 : if (code.is_tree_code ())
1366 : {
1367 261991 : direct_optab optab = optab_for_tree_code (tree_code (code), type,
1368 : query_type);
1369 261991 : return (optab != unknown_optab
1370 261991 : && 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 4384 : get_conditional_internal_fn (code_helper code, tree type)
1408 : {
1409 4384 : if (code.is_tree_code ())
1410 4384 : 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 : }
|