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 678467456 : gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
107 : {
108 678467456 : switch (num_ops)
109 : {
110 153910495 : case 1:
111 153910495 : return gimple_resimplify1 (seq, this, valueize);
112 516313374 : case 2:
113 516313374 : return gimple_resimplify2 (seq, this, valueize);
114 7284377 : case 3:
115 7284377 : return gimple_resimplify3 (seq, this, valueize);
116 246321 : case 4:
117 246321 : return gimple_resimplify4 (seq, this, valueize);
118 24815 : case 5:
119 24815 : return gimple_resimplify5 (seq, this, valueize);
120 604003 : case 6:
121 604003 : return gimple_resimplify6 (seq, this, valueize);
122 84071 : case 7:
123 84071 : 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 633249 : gimple_match_op::operands_occurs_in_abnormal_phi() const
133 : {
134 1776112 : for (unsigned int i = 0; i < num_ops; i++)
135 : {
136 1142865 : if (TREE_CODE (ops[i]) == SSA_NAME
137 1142865 : && 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 735984558 : constant_for_folding (tree t)
148 : {
149 735984558 : return (CONSTANT_CLASS_P (t)
150 : /* The following is only interesting to string builtins. */
151 735984558 : || (TREE_CODE (t) == ADDR_EXPR
152 13653472 : && 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 12720 : convert_conditional_op (gimple_match_op *orig_op,
160 : gimple_match_op *new_op)
161 : {
162 12720 : internal_fn ifn;
163 12720 : if (orig_op->code.is_tree_code ())
164 11570 : 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 12720 : if (ifn == IFN_LAST)
173 : return false;
174 11130 : unsigned int num_ops = orig_op->num_ops;
175 11130 : unsigned int num_cond_ops = 2;
176 11130 : 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 11130 : new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + num_cond_ops);
183 11130 : new_op->ops[0] = orig_op->cond.cond;
184 34534 : for (unsigned int i = 0; i < num_ops; ++i)
185 23404 : new_op->ops[i + 1] = orig_op->ops[i];
186 11130 : 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 11130 : if (else_value
191 11130 : && !types_compatible_p (orig_op->type, TREE_TYPE (else_value)))
192 : return false;
193 :
194 11130 : if (!else_value)
195 6 : else_value = targetm.preferred_else_value (ifn, orig_op->type,
196 6 : num_ops, orig_op->ops);
197 11130 : new_op->ops[num_ops + 1] = else_value;
198 11130 : 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 1176387062 : do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
210 : {
211 1176387062 : if (valueize && TREE_CODE (op) == SSA_NAME)
212 : {
213 743314367 : tree tem = valueize (op);
214 743314367 : if (tem && tem != op)
215 : {
216 51566829 : op = tem;
217 51566829 : valueized = true;
218 : }
219 : }
220 1176387062 : 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 2901542 : maybe_build_generic_op (gimple_match_op *res_op)
228 : {
229 2901542 : tree_code code = (tree_code) res_op->code;
230 2901542 : tree val;
231 2901542 : switch (code)
232 : {
233 10229 : case REALPART_EXPR:
234 10229 : case IMAGPART_EXPR:
235 10229 : case VIEW_CONVERT_EXPR:
236 10229 : val = build1 (code, res_op->type, res_op->ops[0]);
237 10229 : res_op->set_value (val);
238 10229 : break;
239 86970 : case BIT_FIELD_REF:
240 86970 : val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
241 : res_op->ops[2]);
242 86970 : REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
243 86970 : res_op->set_value (val);
244 86970 : break;
245 2901542 : default:;
246 : }
247 2901542 : }
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 8295 : build_call_internal (internal_fn fn, gimple_match_op *res_op)
254 : {
255 8295 : if (direct_internal_fn_p (fn))
256 : {
257 8263 : tree_pair types = direct_internal_fn_types (fn, res_op->type,
258 8263 : res_op->ops);
259 8263 : 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 2 : case IFN_BSWAP:
270 2 : case IFN_BITREVERSE:
271 : /* For these 8 builtins large/huge _BitInt operand is ok
272 : before bitint lowering pass. */
273 2 : if (res_op->num_ops >= 1
274 2 : && BITINT_TYPE_P (TREE_TYPE (res_op->ops[0]))
275 2 : && (TYPE_PRECISION (TREE_TYPE (res_op->ops[0]))
276 4 : > MAX_FIXED_MODE_SIZE)
277 2 : && cfun
278 4 : && (cfun->curr_properties & PROP_gimple_lbitint) == 0)
279 : break;
280 74 : return NULL;
281 :
282 : default:
283 : return NULL;
284 : }
285 : }
286 : }
287 33208 : return gimple_build_call_internal (fn, res_op->num_ops,
288 : res_op->op_or_null (0),
289 : res_op->op_or_null (1),
290 : res_op->op_or_null (2),
291 : res_op->op_or_null (3),
292 : res_op->op_or_null (4),
293 : res_op->op_or_null (5),
294 8221 : res_op->op_or_null (6));
295 : }
296 :
297 : /* RES_OP is the result of a simplification. If it is conditional,
298 : try to replace it with the equivalent UNCOND form, such as an
299 : IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the
300 : result of the replacement if appropriate, adding any new statements to
301 : SEQ and using VALUEIZE as the valueization function. Return true if
302 : this resimplification occurred and resulted in at least one change. */
303 :
304 : static bool
305 636668525 : maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
306 : tree (*valueize) (tree))
307 : {
308 636668525 : if (!res_op->cond.cond)
309 : return false;
310 :
311 15739 : if (!res_op->cond.else_value
312 15739 : && res_op->code.is_tree_code ())
313 : {
314 : /* The "else" value doesn't matter. If the "then" value is a
315 : gimple value, just use it unconditionally. This isn't a
316 : simplification in itself, since there was no operation to
317 : build in the first place. */
318 1772 : if (gimple_simplified_result_is_gimple_val (res_op))
319 : {
320 1760 : res_op->cond.cond = NULL_TREE;
321 1760 : return false;
322 : }
323 :
324 : /* Likewise if the operation would not trap. */
325 12 : bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
326 12 : && TYPE_OVERFLOW_TRAPS (res_op->type));
327 12 : tree_code op_code = (tree_code) res_op->code;
328 12 : bool op_could_trap;
329 :
330 : /* COND_EXPR will trap if, and only if, the condition
331 : traps and hence we have to check this. For all other operations, we
332 : don't need to consider the operands. */
333 12 : if (op_code == COND_EXPR)
334 0 : op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
335 : else
336 24 : op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
337 12 : FLOAT_TYPE_P (res_op->type),
338 : honor_trapv,
339 : res_op->op_or_null (1));
340 :
341 12 : if (!op_could_trap)
342 : {
343 6 : res_op->cond.cond = NULL_TREE;
344 6 : return false;
345 : }
346 : }
347 :
348 : /* If the "then" value is a gimple value and the "else" value matters,
349 : create a (VEC_)COND_EXPR between them, then see if it can be further
350 : simplified. */
351 13973 : gimple_match_op new_op;
352 13973 : if (res_op->cond.else_value
353 13973 : && gimple_simplified_result_is_gimple_val (res_op))
354 : {
355 1253 : if (VECTOR_TYPE_P (res_op->type))
356 : {
357 1253 : tree len = res_op->cond.len;
358 1253 : if (!len)
359 1253 : new_op.set_op (VEC_COND_EXPR, res_op->type,
360 : res_op->cond.cond, res_op->ops[0],
361 : res_op->cond.else_value);
362 : else
363 0 : new_op.set_op (IFN_VCOND_MASK_LEN, res_op->type,
364 : res_op->cond.cond, res_op->ops[0],
365 : res_op->cond.else_value,
366 : res_op->cond.len, res_op->cond.bias);
367 : }
368 : else
369 0 : new_op.set_op (COND_EXPR, res_op->type,
370 : res_op->cond.cond, res_op->ops[0],
371 : res_op->cond.else_value);
372 1253 : *res_op = new_op;
373 1253 : return gimple_resimplify3 (seq, res_op, valueize);
374 : }
375 :
376 : /* Otherwise try rewriting the operation as an IFN_COND_* call.
377 : Again, this isn't a simplification in itself, since it's what
378 : RES_OP already described. */
379 12720 : if (convert_conditional_op (res_op, &new_op))
380 11130 : *res_op = new_op;
381 :
382 : return false;
383 : }
384 :
385 : /* If RES_OP is a call to a conditional internal function, try simplifying
386 : the associated unconditional operation and using the result to build
387 : a new conditional operation. For example, if RES_OP is:
388 :
389 : IFN_COND_ADD (COND, A, B, ELSE)
390 :
391 : try simplifying (plus A B) and using the result to build a replacement
392 : for the whole IFN_COND_ADD.
393 :
394 : Return true if this approach led to a simplification, otherwise leave
395 : RES_OP unchanged (and so suitable for other simplifications). When
396 : returning true, add any new statements to SEQ and use VALUEIZE as the
397 : valueization function.
398 :
399 : RES_OP is known to be a call to IFN. */
400 :
401 : static bool
402 3098227 : try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
403 : gimple_seq *seq, tree (*valueize) (tree))
404 : {
405 3098227 : code_helper op;
406 3098227 : tree_code code = conditional_internal_fn_code (ifn);
407 3098227 : int len_index = internal_fn_len_index (ifn);
408 3098227 : if (code != ERROR_MARK)
409 12022 : op = code;
410 : else
411 : {
412 3086205 : ifn = get_unconditional_internal_fn (ifn);
413 3086205 : if (ifn == IFN_LAST)
414 : return false;
415 1150 : op = as_combined_fn (ifn);
416 : }
417 :
418 13172 : unsigned int num_ops = res_op->num_ops;
419 : /* num_cond_ops = 2 for COND_ADD (MASK and ELSE)
420 : whereas num_cond_ops = 4 for COND_LEN_ADD (MASK, ELSE, LEN and BIAS). */
421 13172 : unsigned int num_cond_ops = len_index < 0 ? 2 : 4;
422 13172 : tree else_value
423 13172 : = len_index < 0 ? res_op->ops[num_ops - 1] : res_op->ops[num_ops - 3];
424 13172 : tree len = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 2];
425 0 : tree bias = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 1];
426 13172 : gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
427 13172 : else_value, len, bias),
428 13172 : op, res_op->type, num_ops - num_cond_ops);
429 :
430 13172 : memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
431 13172 : switch (num_ops - num_cond_ops)
432 : {
433 0 : case 1:
434 0 : if (!gimple_resimplify1 (seq, &cond_op, valueize))
435 : return false;
436 : break;
437 12022 : case 2:
438 12022 : if (!gimple_resimplify2 (seq, &cond_op, valueize))
439 : return false;
440 : break;
441 1150 : case 3:
442 1150 : if (!gimple_resimplify3 (seq, &cond_op, valueize))
443 : return false;
444 : break;
445 0 : default:
446 0 : gcc_unreachable ();
447 : }
448 2947 : *res_op = cond_op;
449 2947 : maybe_resimplify_conditional_op (seq, res_op, valueize);
450 2947 : return true;
451 : }
452 :
453 : /* Helper for the autogenerated code, valueize OP. */
454 :
455 : tree
456 725084821 : do_valueize (tree (*valueize)(tree), tree op)
457 : {
458 725084821 : if (valueize && TREE_CODE (op) == SSA_NAME)
459 : {
460 539076687 : tree tem = valueize (op);
461 539076687 : if (tem)
462 : return tem;
463 : }
464 : return op;
465 : }
466 :
467 : /* Push the exploded expression described by RES_OP as a statement to
468 : SEQ if necessary and return a gimple value denoting the value of the
469 : expression. If RES is not NULL then the result will be always RES
470 : and even gimple values are pushed to SEQ. */
471 :
472 : tree
473 12833207 : maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
474 : {
475 12833207 : tree *ops = res_op->ops;
476 12833207 : unsigned num_ops = res_op->num_ops;
477 :
478 : /* The caller should have converted conditional operations into an UNCOND
479 : form and resimplified as appropriate. The conditional form only
480 : survives this far if that conversion failed. */
481 12833207 : if (res_op->cond.cond)
482 : return NULL_TREE;
483 :
484 12832808 : if (res_op->code.is_tree_code ())
485 : {
486 12817011 : if (!res
487 12817011 : && gimple_simplified_result_is_gimple_val (res_op))
488 7007786 : return ops[0];
489 5809225 : if (mprts_hook)
490 : {
491 2138697 : tree tem = mprts_hook (res_op);
492 2138697 : if (tem)
493 : return tem;
494 : }
495 : }
496 :
497 5770331 : if (!seq)
498 : return NULL_TREE;
499 :
500 : /* Play safe and do not allow abnormals to be mentioned in
501 : newly created statements. */
502 2142139 : for (unsigned int i = 0; i < num_ops; ++i)
503 1364649 : if (TREE_CODE (ops[i]) == SSA_NAME
504 1364649 : && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
505 : return NULL_TREE;
506 :
507 777490 : if (res_op->code.is_tree_code ())
508 : {
509 764462 : auto code = tree_code (res_op->code);
510 764462 : if (!res)
511 : {
512 683766 : if (gimple_in_ssa_p (cfun))
513 682797 : res = make_ssa_name (res_op->type);
514 : else
515 969 : res = create_tmp_reg (res_op->type);
516 : }
517 764462 : maybe_build_generic_op (res_op);
518 1953857 : gimple *new_stmt = gimple_build_assign (res, code,
519 : res_op->op_or_null (0),
520 : res_op->op_or_null (1),
521 : res_op->op_or_null (2));
522 764462 : gimple_seq_add_stmt_without_update (seq, new_stmt);
523 764462 : return res;
524 : }
525 : else
526 : {
527 13028 : gcc_assert (num_ops != 0);
528 13028 : auto fn = combined_fn (res_op->code);
529 13028 : gcall *new_stmt = NULL;
530 13028 : if (internal_fn_p (fn))
531 : {
532 : /* Generate the given function if we can. */
533 8295 : internal_fn ifn = as_internal_fn (fn);
534 :
535 : /* We can't and should not emit calls to non-const functions. */
536 8295 : if (!(internal_fn_flags (ifn) & ECF_CONST))
537 : return NULL_TREE;
538 :
539 8295 : new_stmt = build_call_internal (ifn, res_op);
540 8295 : if (!new_stmt)
541 : return NULL_TREE;
542 : }
543 : else
544 : {
545 : /* Find the function we want to call. */
546 4733 : tree decl = builtin_decl_implicit (as_builtin_fn (fn));
547 4733 : if (!decl)
548 : return NULL;
549 :
550 : /* We can't and should not emit calls to non-const functions. */
551 4727 : if (!(flags_from_decl_or_type (decl) & ECF_CONST))
552 : return NULL;
553 :
554 8108 : new_stmt = gimple_build_call (decl, num_ops,
555 : res_op->op_or_null (0),
556 : res_op->op_or_null (1),
557 : res_op->op_or_null (2),
558 : res_op->op_or_null (3),
559 : res_op->op_or_null (4));
560 : }
561 12187 : if (!res)
562 : {
563 1255 : if (gimple_in_ssa_p (cfun))
564 1255 : res = make_ssa_name (res_op->type);
565 : else
566 0 : res = create_tmp_reg (res_op->type);
567 : }
568 12187 : gimple_call_set_lhs (new_stmt, res);
569 12187 : gimple_seq_add_stmt_without_update (seq, new_stmt);
570 12187 : return res;
571 : }
572 : }
573 :
574 :
575 : /* Public API overloads follow for operation being tree_code or
576 : built_in_function and for one to three operands or arguments.
577 : They return NULL_TREE if nothing could be simplified or
578 : the resulting simplified value with parts pushed to SEQ.
579 : If SEQ is NULL then if the simplification needs to create
580 : new stmts it will fail. If VALUEIZE is non-NULL then all
581 : SSA names will be valueized using that hook prior to
582 : applying simplifications. */
583 :
584 : /* Unary ops. */
585 :
586 : tree
587 338645 : gimple_simplify (enum tree_code code, tree type,
588 : tree op0,
589 : gimple_seq *seq, tree (*valueize)(tree))
590 : {
591 338645 : if (constant_for_folding (op0))
592 : {
593 29410 : tree res = const_unop (code, type, op0);
594 29410 : if (res != NULL_TREE
595 29162 : && CONSTANT_CLASS_P (res))
596 : return res;
597 : }
598 :
599 309483 : gimple_match_op res_op;
600 309483 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
601 : return NULL_TREE;
602 11115 : return maybe_push_res_to_seq (&res_op, seq);
603 : }
604 :
605 : /* Binary ops. */
606 :
607 : tree
608 25128725 : gimple_simplify (enum tree_code code, tree type,
609 : tree op0, tree op1,
610 : gimple_seq *seq, tree (*valueize)(tree))
611 : {
612 25128725 : if (constant_for_folding (op0) && constant_for_folding (op1))
613 : {
614 1761994 : tree res = const_binop (code, type, op0, op1);
615 1761994 : if (res != NULL_TREE
616 1760400 : && CONSTANT_CLASS_P (res))
617 : return res;
618 : }
619 :
620 : /* Canonicalize operand order both for matching and fallback stmt
621 : generation. */
622 23368325 : if ((commutative_tree_code (code)
623 6694009 : || TREE_CODE_CLASS (code) == tcc_comparison)
624 29938977 : && tree_swap_operands_p (op0, op1))
625 : {
626 42564 : std::swap (op0, op1);
627 42564 : if (TREE_CODE_CLASS (code) == tcc_comparison)
628 3838 : code = swap_tree_comparison (code);
629 : }
630 :
631 23368325 : gimple_match_op res_op;
632 23368325 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
633 : return NULL_TREE;
634 2535970 : return maybe_push_res_to_seq (&res_op, seq);
635 : }
636 :
637 : /* Ternary ops. */
638 :
639 : tree
640 44818 : gimple_simplify (enum tree_code code, tree type,
641 : tree op0, tree op1, tree op2,
642 : gimple_seq *seq, tree (*valueize)(tree))
643 : {
644 46105 : if (constant_for_folding (op0) && constant_for_folding (op1)
645 46105 : && constant_for_folding (op2))
646 : {
647 1287 : tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
648 1287 : if (res != NULL_TREE
649 1287 : && CONSTANT_CLASS_P (res))
650 : return res;
651 : }
652 :
653 : /* Canonicalize operand order both for matching and fallback stmt
654 : generation. */
655 43531 : if (commutative_ternary_tree_code (code)
656 43531 : && tree_swap_operands_p (op0, op1))
657 : std::swap (op0, op1);
658 :
659 43531 : gimple_match_op res_op;
660 43531 : if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
661 : return NULL_TREE;
662 11841 : return maybe_push_res_to_seq (&res_op, seq);
663 : }
664 :
665 : /* Builtin or internal function with one argument. */
666 :
667 : tree
668 24604 : gimple_simplify (combined_fn fn, tree type,
669 : tree arg0,
670 : gimple_seq *seq, tree (*valueize)(tree))
671 : {
672 24604 : if (constant_for_folding (arg0))
673 : {
674 0 : tree res = fold_const_call (fn, type, arg0);
675 0 : if (res && CONSTANT_CLASS_P (res))
676 : return res;
677 : }
678 :
679 24604 : gimple_match_op res_op;
680 24604 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
681 : return NULL_TREE;
682 0 : return maybe_push_res_to_seq (&res_op, seq);
683 : }
684 :
685 : /* Builtin or internal function with two arguments. */
686 :
687 : tree
688 0 : gimple_simplify (combined_fn fn, tree type,
689 : tree arg0, tree arg1,
690 : gimple_seq *seq, tree (*valueize)(tree))
691 : {
692 0 : if (constant_for_folding (arg0)
693 0 : && constant_for_folding (arg1))
694 : {
695 0 : tree res = fold_const_call (fn, type, arg0, arg1);
696 0 : if (res && CONSTANT_CLASS_P (res))
697 : return res;
698 : }
699 :
700 0 : gimple_match_op res_op;
701 0 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
702 : return NULL_TREE;
703 0 : return maybe_push_res_to_seq (&res_op, seq);
704 : }
705 :
706 : /* Builtin or internal function with three arguments. */
707 :
708 : tree
709 0 : gimple_simplify (combined_fn fn, tree type,
710 : tree arg0, tree arg1, tree arg2,
711 : gimple_seq *seq, tree (*valueize)(tree))
712 : {
713 0 : if (constant_for_folding (arg0)
714 0 : && constant_for_folding (arg1)
715 0 : && constant_for_folding (arg2))
716 : {
717 0 : tree res = fold_const_call (fn, type, arg0, arg1, arg2);
718 0 : if (res && CONSTANT_CLASS_P (res))
719 : return res;
720 : }
721 :
722 0 : gimple_match_op res_op;
723 0 : if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
724 : return NULL_TREE;
725 0 : return maybe_push_res_to_seq (&res_op, seq);
726 : }
727 :
728 : /* Common subroutine of gimple_extract_op and gimple_simplify. Try to
729 : describe STMT in RES_OP, returning true on success. Before recording
730 : an operand, call:
731 :
732 : - VALUEIZE_OP for all top-level operand
733 :
734 : This routine takes a tree argument and returns a tree. */
735 :
736 : template<typename ValueizeOp>
737 : inline bool
738 1319386891 : gimple_extract (gimple *stmt, gimple_match_op *res_op,
739 : ValueizeOp valueize_op)
740 : {
741 1319386891 : switch (gimple_code (stmt))
742 : {
743 610367683 : case GIMPLE_ASSIGN:
744 : {
745 610367683 : enum tree_code code = gimple_assign_rhs_code (stmt);
746 610367683 : tree type = TREE_TYPE (gimple_assign_lhs (stmt));
747 610367683 : switch (gimple_assign_rhs_class (stmt))
748 : {
749 281406368 : case GIMPLE_SINGLE_RHS:
750 281406368 : if (code == REALPART_EXPR
751 : || code == IMAGPART_EXPR
752 281406368 : || code == VIEW_CONVERT_EXPR)
753 : {
754 7857657 : tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
755 : /* op0 needs to be a SSA name or an min invariant. */
756 7857657 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
757 : return false;
758 5656528 : res_op->set_op (code, type, valueize_op (op0));
759 5656528 : return true;
760 : }
761 273548711 : else if (code == BIT_FIELD_REF)
762 : {
763 1752622 : tree rhs1 = gimple_assign_rhs1 (stmt);
764 1752622 : tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
765 : /* op0 needs to be a SSA name or an min invariant. */
766 1752622 : if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
767 : return false;
768 1139521 : res_op->set_op (code, type, op0,
769 1139521 : TREE_OPERAND (rhs1, 1),
770 1139521 : TREE_OPERAND (rhs1, 2),
771 1139521 : REF_REVERSE_STORAGE_ORDER (rhs1));
772 1139521 : return true;
773 : }
774 271796089 : else if (code == SSA_NAME)
775 : {
776 44735169 : tree op0 = gimple_assign_rhs1 (stmt);
777 44735169 : res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
778 44735169 : return true;
779 : }
780 : break;
781 83385393 : case GIMPLE_UNARY_RHS:
782 : {
783 83385393 : tree rhs1 = gimple_assign_rhs1 (stmt);
784 83385393 : res_op->set_op (code, type, valueize_op (rhs1));
785 83385393 : return true;
786 : }
787 244257792 : case GIMPLE_BINARY_RHS:
788 : {
789 244257792 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
790 244257792 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
791 244257792 : res_op->set_op (code, type, rhs1, rhs2);
792 244257792 : return true;
793 : }
794 1318130 : case GIMPLE_TERNARY_RHS:
795 : {
796 1318130 : tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
797 1318130 : tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
798 1318130 : tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
799 1318130 : res_op->set_op (code, type, rhs1, rhs2, rhs3);
800 1318130 : return true;
801 : }
802 0 : default:
803 0 : gcc_unreachable ();
804 : }
805 : break;
806 : }
807 :
808 70071691 : case GIMPLE_CALL:
809 : /* ??? This way we can't simplify calls with side-effects. */
810 70071691 : if (gimple_call_lhs (stmt) != NULL_TREE
811 36915662 : && gimple_call_num_args (stmt) >= 1
812 104969535 : && gimple_call_num_args (stmt) <= 7)
813 : {
814 : combined_fn cfn;
815 34812215 : if (gimple_call_internal_p (stmt))
816 3156169 : cfn = as_combined_fn (gimple_call_internal_fn (stmt));
817 : else
818 : {
819 31656046 : tree fn = gimple_call_fn (stmt);
820 31656046 : if (!fn)
821 : return false;
822 :
823 31656046 : fn = valueize_op (fn);
824 31656046 : if (TREE_CODE (fn) != ADDR_EXPR
825 31656046 : || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
826 : return false;
827 :
828 30166578 : tree decl = TREE_OPERAND (fn, 0);
829 30166578 : if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
830 30166578 : || !gimple_builtin_call_types_compatible_p (stmt, decl))
831 19855805 : return false;
832 :
833 10310773 : cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
834 : }
835 :
836 13466942 : unsigned int num_args = gimple_call_num_args (stmt);
837 13466942 : res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
838 44597993 : for (unsigned i = 0; i < num_args; ++i)
839 62003994 : res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
840 : return true;
841 : }
842 : break;
843 :
844 244276646 : case GIMPLE_COND:
845 : {
846 244276646 : tree lhs = valueize_op (gimple_cond_lhs (stmt));
847 244276646 : tree rhs = valueize_op (gimple_cond_rhs (stmt));
848 244276646 : res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
849 244276646 : return true;
850 : }
851 :
852 : default:
853 : break;
854 : }
855 :
856 : return false;
857 : }
858 :
859 : /* Try to describe STMT in RES_OP, returning true on success.
860 : For GIMPLE_CONDs, describe the condition that is being tested.
861 : For GIMPLE_ASSIGNs, describe the rhs of the assignment.
862 : For GIMPLE_CALLs, describe the call. */
863 :
864 : bool
865 2156305 : gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
866 : {
867 2156305 : auto nop = [](tree op) { return op; };
868 2156305 : return gimple_extract (stmt, res_op, nop);
869 : }
870 :
871 : /* The main STMT based simplification entry. It is used by the fold_stmt
872 : and the fold_stmt_to_constant APIs. */
873 :
874 : bool
875 1317230586 : gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
876 : tree (*valueize)(tree), tree (*top_valueize)(tree))
877 : {
878 1317230586 : bool valueized = false;
879 2493617648 : auto valueize_op = [&](tree op)
880 : {
881 1176387062 : return do_valueize (op, top_valueize, valueized);
882 1317230586 : };
883 :
884 1317230586 : if (!gimple_extract (stmt, res_op, valueize_op))
885 : return false;
886 :
887 636794629 : if (res_op->code.is_internal_fn ())
888 : {
889 3098227 : internal_fn ifn = internal_fn (res_op->code);
890 3098227 : if (try_conditional_simplification (ifn, res_op, seq, valueize))
891 : return true;
892 : }
893 :
894 636791682 : if (!res_op->reverse
895 636791682 : && res_op->num_ops
896 1273583364 : && res_op->resimplify (seq, valueize))
897 : return true;
898 :
899 570224873 : return valueized;
900 : }
901 :
902 : /* Helper that matches and simplifies the toplevel result from
903 : a gimple_simplify run (where we don't want to build
904 : a stmt in case it's used in in-place folding). Replaces
905 : RES_OP with a simplified and/or canonicalized result and
906 : returns whether any change was made. */
907 :
908 : static bool
909 153910495 : gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
910 : tree (*valueize)(tree))
911 : {
912 153910495 : if (constant_for_folding (res_op->ops[0]))
913 : {
914 13451367 : tree tem = NULL_TREE;
915 13451367 : if (res_op->code.is_tree_code ())
916 : {
917 12246984 : auto code = tree_code (res_op->code);
918 12246984 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
919 11441278 : && TREE_CODE_LENGTH (code) == 1)
920 11441278 : tem = const_unop (code, res_op->type, res_op->ops[0]);
921 : }
922 : else
923 1204383 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
924 : res_op->ops[0]);
925 12645661 : if (tem != NULL_TREE
926 11374603 : && CONSTANT_CLASS_P (tem))
927 : {
928 11374603 : if (TREE_OVERFLOW_P (tem))
929 2753 : tem = drop_tree_overflow (tem);
930 11374603 : res_op->set_value (tem);
931 11374603 : maybe_resimplify_conditional_op (seq, res_op, valueize);
932 11374603 : return true;
933 : }
934 : }
935 :
936 : /* Limit recursion, there are cases like PR80887 and others, for
937 : example when value-numbering presents us with unfolded expressions
938 : that we are really not prepared to handle without eventual
939 : oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
940 : itself as available expression. */
941 142535892 : static unsigned depth;
942 142535892 : if (depth > 10)
943 : {
944 2 : if (dump_file && (dump_flags & TDF_FOLDING))
945 0 : fprintf (dump_file, "Aborting expression simplification due to "
946 : "deep recursion\n");
947 2 : return false;
948 : }
949 :
950 142535890 : ++depth;
951 142535890 : gimple_match_op res_op2 (*res_op);
952 142535890 : if (gimple_simplify (&res_op2, seq, valueize,
953 : res_op->code, res_op->type, res_op->ops[0]))
954 : {
955 2622160 : --depth;
956 2622160 : *res_op = res_op2;
957 2622160 : return true;
958 : }
959 139913730 : --depth;
960 :
961 139913730 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
962 : return true;
963 :
964 : return false;
965 : }
966 :
967 : /* Helper that matches and simplifies the toplevel result from
968 : a gimple_simplify run (where we don't want to build
969 : a stmt in case it's used in in-place folding). Replaces
970 : RES_OP with a simplified and/or canonicalized result and
971 : returns whether any change was made. */
972 :
973 : static bool
974 516325396 : gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
975 : tree (*valueize)(tree))
976 : {
977 516325396 : if (constant_for_folding (res_op->ops[0])
978 516325396 : && constant_for_folding (res_op->ops[1]))
979 : {
980 22777010 : tree tem = NULL_TREE;
981 22777010 : if (res_op->code.is_tree_code ())
982 : {
983 22645384 : auto code = tree_code (res_op->code);
984 22645384 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
985 22645384 : && TREE_CODE_LENGTH (code) == 2)
986 22645384 : tem = const_binop (code, res_op->type,
987 : res_op->ops[0], res_op->ops[1]);
988 : }
989 : else
990 131626 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
991 : res_op->ops[0], res_op->ops[1]);
992 22777010 : if (tem != NULL_TREE
993 22601260 : && CONSTANT_CLASS_P (tem))
994 : {
995 22601214 : if (TREE_OVERFLOW_P (tem))
996 671 : tem = drop_tree_overflow (tem);
997 22601214 : res_op->set_value (tem);
998 22601214 : maybe_resimplify_conditional_op (seq, res_op, valueize);
999 22601214 : return true;
1000 : }
1001 : }
1002 :
1003 : /* Canonicalize operand order. */
1004 493724182 : bool canonicalized = false;
1005 493724182 : bool is_comparison
1006 493724182 : = (res_op->code.is_tree_code ()
1007 493724182 : && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison);
1008 236714618 : if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type))
1009 427380666 : && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
1010 : {
1011 8338341 : std::swap (res_op->ops[0], res_op->ops[1]);
1012 8338341 : if (is_comparison)
1013 3356738 : res_op->code = swap_tree_comparison (tree_code (res_op->code));
1014 : canonicalized = true;
1015 : }
1016 :
1017 : /* Limit recursion, see gimple_resimplify1. */
1018 493724182 : static unsigned depth;
1019 493724182 : if (depth > 10)
1020 : {
1021 43699 : if (dump_file && (dump_flags & TDF_FOLDING))
1022 0 : fprintf (dump_file, "Aborting expression simplification due to "
1023 : "deep recursion\n");
1024 43699 : return false;
1025 : }
1026 :
1027 493680483 : ++depth;
1028 493680483 : gimple_match_op res_op2 (*res_op);
1029 493680483 : if (gimple_simplify (&res_op2, seq, valueize,
1030 : res_op->code, res_op->type,
1031 : res_op->ops[0], res_op->ops[1]))
1032 : {
1033 38716250 : --depth;
1034 38716250 : *res_op = res_op2;
1035 38716250 : return true;
1036 : }
1037 454964233 : --depth;
1038 :
1039 454964233 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1040 : return true;
1041 :
1042 : return canonicalized;
1043 : }
1044 :
1045 : /* Helper that matches and simplifies the toplevel result from
1046 : a gimple_simplify run (where we don't want to build
1047 : a stmt in case it's used in in-place folding). Replaces
1048 : RES_OP with a simplified and/or canonicalized result and
1049 : returns whether any change was made. */
1050 :
1051 : static bool
1052 7286780 : gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
1053 : tree (*valueize)(tree))
1054 : {
1055 7286780 : if (constant_for_folding (res_op->ops[0])
1056 871484 : && constant_for_folding (res_op->ops[1])
1057 7949358 : && constant_for_folding (res_op->ops[2]))
1058 : {
1059 89403 : tree tem = NULL_TREE;
1060 89403 : if (res_op->code.is_tree_code ())
1061 : {
1062 51159 : auto code = tree_code (res_op->code);
1063 51159 : if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
1064 51159 : && TREE_CODE_LENGTH (code) == 3)
1065 51159 : tem = fold_ternary/*_to_constant*/ (code, res_op->type,
1066 : res_op->ops[0], res_op->ops[1],
1067 : res_op->ops[2]);
1068 : }
1069 : else
1070 38244 : tem = fold_const_call (combined_fn (res_op->code), res_op->type,
1071 : res_op->ops[0], res_op->ops[1], res_op->ops[2]);
1072 89403 : if (tem != NULL_TREE
1073 51139 : && CONSTANT_CLASS_P (tem))
1074 : {
1075 50971 : if (TREE_OVERFLOW_P (tem))
1076 4 : tem = drop_tree_overflow (tem);
1077 50971 : res_op->set_value (tem);
1078 50971 : maybe_resimplify_conditional_op (seq, res_op, valueize);
1079 50971 : return true;
1080 : }
1081 : }
1082 :
1083 : /* Canonicalize operand order. */
1084 7235809 : bool canonicalized = false;
1085 7235809 : int argno = first_commutative_argument (res_op->code, res_op->type);
1086 7235809 : if (argno >= 0
1087 7235809 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1088 : {
1089 1185 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1090 1185 : canonicalized = true;
1091 : }
1092 :
1093 : /* Limit recursion, see gimple_resimplify1. */
1094 7235809 : static unsigned depth;
1095 7235809 : if (depth > 10)
1096 : {
1097 33 : if (dump_file && (dump_flags & TDF_FOLDING))
1098 0 : fprintf (dump_file, "Aborting expression simplification due to "
1099 : "deep recursion\n");
1100 33 : return false;
1101 : }
1102 :
1103 7235776 : ++depth;
1104 7235776 : gimple_match_op res_op2 (*res_op);
1105 7235776 : if (gimple_simplify (&res_op2, seq, valueize,
1106 : res_op->code, res_op->type,
1107 : res_op->ops[0], res_op->ops[1], res_op->ops[2]))
1108 : {
1109 434159 : --depth;
1110 434159 : *res_op = res_op2;
1111 434159 : return true;
1112 : }
1113 6801617 : --depth;
1114 :
1115 6801617 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1116 : return true;
1117 :
1118 : return canonicalized;
1119 : }
1120 :
1121 : /* Helper that matches and simplifies the toplevel result from
1122 : a gimple_simplify run (where we don't want to build
1123 : a stmt in case it's used in in-place folding). Replaces
1124 : RES_OP with a simplified and/or canonicalized result and
1125 : returns whether any change was made. */
1126 :
1127 : static bool
1128 246321 : gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
1129 : tree (*valueize)(tree))
1130 : {
1131 : /* No constant folding is defined for four-operand functions. */
1132 :
1133 : /* Canonicalize operand order. */
1134 246321 : bool canonicalized = false;
1135 246321 : int argno = first_commutative_argument (res_op->code, res_op->type);
1136 246321 : if (argno >= 0
1137 246321 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1138 : {
1139 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1140 0 : canonicalized = true;
1141 : }
1142 :
1143 : /* Limit recursion, see gimple_resimplify1. */
1144 246321 : static unsigned depth;
1145 246321 : if (depth > 10)
1146 : {
1147 0 : if (dump_file && (dump_flags & TDF_FOLDING))
1148 0 : fprintf (dump_file, "Aborting expression simplification due to "
1149 : "deep recursion\n");
1150 0 : return false;
1151 : }
1152 :
1153 246321 : ++depth;
1154 246321 : gimple_match_op res_op2 (*res_op);
1155 246321 : if (gimple_simplify (&res_op2, seq, valueize,
1156 : res_op->code, res_op->type,
1157 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1158 : res_op->ops[3]))
1159 : {
1160 0 : --depth;
1161 0 : *res_op = res_op2;
1162 0 : return true;
1163 : }
1164 246321 : --depth;
1165 :
1166 246321 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1167 : return true;
1168 :
1169 : return canonicalized;
1170 : }
1171 :
1172 : /* Helper that matches and simplifies the toplevel result from
1173 : a gimple_simplify run (where we don't want to build
1174 : a stmt in case it's used in in-place folding). Replaces
1175 : RES_OP with a simplified and/or canonicalized result and
1176 : returns whether any change was made. */
1177 :
1178 : static bool
1179 24815 : gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
1180 : tree (*valueize)(tree))
1181 : {
1182 : /* No constant folding is defined for five-operand functions. */
1183 :
1184 : /* Canonicalize operand order. */
1185 24815 : bool canonicalized = false;
1186 24815 : int argno = first_commutative_argument (res_op->code, res_op->type);
1187 24815 : if (argno >= 0
1188 24815 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1189 : {
1190 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1191 0 : canonicalized = true;
1192 : }
1193 :
1194 24815 : gimple_match_op res_op2 (*res_op);
1195 24815 : if (gimple_simplify (&res_op2, seq, valueize,
1196 : res_op->code, res_op->type,
1197 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1198 : res_op->ops[3], res_op->ops[4]))
1199 : {
1200 0 : *res_op = res_op2;
1201 0 : return true;
1202 : }
1203 :
1204 24815 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1205 : return true;
1206 :
1207 : return canonicalized;
1208 : }
1209 :
1210 : /* Helper that matches and simplifies the toplevel result from
1211 : a gimple_simplify run (where we don't want to build
1212 : a stmt in case it's used in in-place folding). Replaces
1213 : RES_OP with a simplified and/or canonicalized result and
1214 : returns whether any change was made. */
1215 :
1216 : static bool
1217 604003 : gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
1218 : tree (*valueize)(tree))
1219 : {
1220 : /* No constant folding is defined for six-operand functions. */
1221 :
1222 : /* Canonicalize operand order. */
1223 604003 : bool canonicalized = false;
1224 604003 : int argno = first_commutative_argument (res_op->code, res_op->type);
1225 604003 : if (argno >= 0
1226 604003 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1227 : {
1228 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1229 0 : canonicalized = true;
1230 : }
1231 :
1232 604003 : gimple_match_op res_op2 (*res_op);
1233 604003 : if (gimple_simplify (&res_op2, seq, valueize,
1234 : res_op->code, res_op->type,
1235 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1236 : res_op->ops[3], res_op->ops[4], res_op->ops[5]))
1237 : {
1238 0 : *res_op = res_op2;
1239 0 : return true;
1240 : }
1241 :
1242 604003 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1243 : return true;
1244 :
1245 : return canonicalized;
1246 : }
1247 :
1248 : /* Helper that matches and simplifies the toplevel result from
1249 : a gimple_simplify run (where we don't want to build
1250 : a stmt in case it's used in in-place folding). Replaces
1251 : RES_OP with a simplified and/or canonicalized result and
1252 : returns whether any change was made. */
1253 :
1254 : static bool
1255 84071 : gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
1256 : tree (*valueize)(tree))
1257 : {
1258 : /* No constant folding is defined for seven-operand functions. */
1259 :
1260 : /* Canonicalize operand order. */
1261 84071 : bool canonicalized = false;
1262 84071 : int argno = first_commutative_argument (res_op->code, res_op->type);
1263 84071 : if (argno >= 0
1264 84071 : && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1265 : {
1266 0 : std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1267 0 : canonicalized = true;
1268 : }
1269 :
1270 84071 : gimple_match_op res_op2 (*res_op);
1271 84071 : if (gimple_simplify (&res_op2, seq, valueize,
1272 : res_op->code, res_op->type,
1273 : res_op->ops[0], res_op->ops[1], res_op->ops[2],
1274 : res_op->ops[3], res_op->ops[4], res_op->ops[5],
1275 : res_op->ops[6]))
1276 : {
1277 0 : *res_op = res_op2;
1278 0 : return true;
1279 : }
1280 :
1281 84071 : if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1282 : return true;
1283 :
1284 : return canonicalized;
1285 : }
1286 :
1287 : /* Return a canonical form for CODE when operating on TYPE. The idea
1288 : is to remove redundant ways of representing the same operation so
1289 : that code_helpers can be hashed and compared for equality.
1290 :
1291 : The only current canonicalization is to replace built-in functions
1292 : with internal functions, in cases where internal-fn.def defines
1293 : such an internal function.
1294 :
1295 : Note that the new code_helper cannot necessarily be used in place of
1296 : the original code_helper. For example, the new code_helper might be
1297 : an internal function that the target does not support. */
1298 :
1299 : code_helper
1300 124927 : canonicalize_code (code_helper code, tree type)
1301 : {
1302 124927 : if (code.is_fn_code ())
1303 6713 : return associated_internal_fn (combined_fn (code), type);
1304 118214 : return code;
1305 : }
1306 :
1307 : /* Return true if CODE is a binary operation and if CODE is commutative when
1308 : operating on type TYPE. */
1309 :
1310 : bool
1311 236782114 : commutative_binary_op_p (code_helper code, tree type)
1312 : {
1313 236782114 : if (code.is_tree_code ())
1314 230825115 : return commutative_tree_code (tree_code (code));
1315 5956999 : auto cfn = combined_fn (code);
1316 5956999 : return commutative_binary_fn_p (associated_internal_fn (cfn, type));
1317 : }
1318 :
1319 : /* Return true if CODE represents a ternary operation and if the first two
1320 : operands are commutative when CODE is operating on TYPE. */
1321 :
1322 : bool
1323 0 : commutative_ternary_op_p (code_helper code, tree type)
1324 : {
1325 0 : if (code.is_tree_code ())
1326 0 : return commutative_ternary_tree_code (tree_code (code));
1327 0 : auto cfn = combined_fn (code);
1328 0 : return commutative_ternary_fn_p (associated_internal_fn (cfn, type));
1329 : }
1330 :
1331 : /* If CODE is commutative in two consecutive operands, return the
1332 : index of the first, otherwise return -1. */
1333 :
1334 : int
1335 8225764 : first_commutative_argument (code_helper code, tree type)
1336 : {
1337 8225764 : if (code.is_tree_code ())
1338 : {
1339 3697399 : auto tcode = tree_code (code);
1340 3697399 : if (commutative_tree_code (tcode)
1341 3697399 : || commutative_ternary_tree_code (tcode))
1342 19665 : return 0;
1343 : return -1;
1344 : }
1345 4528365 : auto cfn = combined_fn (code);
1346 4528365 : return first_commutative_argument (associated_internal_fn (cfn, type));
1347 : }
1348 :
1349 : /* Return true if CODE is a binary operation that is associative when
1350 : operating on type TYPE. */
1351 :
1352 : bool
1353 67352 : associative_binary_op_p (code_helper code, tree type)
1354 : {
1355 67352 : if (code.is_tree_code ())
1356 67300 : return associative_tree_code (tree_code (code));
1357 52 : auto cfn = combined_fn (code);
1358 52 : return associative_binary_fn_p (associated_internal_fn (cfn, type));
1359 : }
1360 :
1361 : /* Return true if the target directly supports operation CODE on type TYPE.
1362 : QUERY_TYPE acts as for optab_for_tree_code. */
1363 :
1364 : bool
1365 290441 : directly_supported_p (code_helper code, tree type, optab_subtype query_type)
1366 : {
1367 290441 : if (code.is_tree_code ())
1368 : {
1369 285621 : direct_optab optab = optab_for_tree_code (tree_code (code), type,
1370 : query_type);
1371 285621 : return (optab != unknown_optab
1372 285621 : && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing);
1373 : }
1374 4820 : gcc_assert (query_type == optab_default
1375 : || (query_type == optab_vector && VECTOR_TYPE_P (type))
1376 : || (query_type == optab_scalar && !VECTOR_TYPE_P (type)));
1377 4820 : internal_fn ifn = associated_internal_fn (combined_fn (code), type);
1378 4820 : return (direct_internal_fn_p (ifn)
1379 4820 : && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
1380 : }
1381 :
1382 : /* As above, overloading the function for conversion-type optabs. */
1383 : bool
1384 3614 : directly_supported_p (code_helper code, tree otype, tree itype,
1385 : optab_subtype query_type)
1386 : {
1387 3614 : if (code.is_tree_code ())
1388 : {
1389 3614 : convert_optab optab = optab_for_tree_code (tree_code (code), itype,
1390 : query_type);
1391 3614 : return (optab != unknown_optab
1392 7228 : && convert_optab_handler (optab, TYPE_MODE (otype),
1393 3614 : TYPE_MODE (itype)) != CODE_FOR_nothing);
1394 : }
1395 0 : gcc_assert (query_type == optab_default
1396 : || (query_type == optab_vector && VECTOR_TYPE_P (itype))
1397 : || (query_type == optab_scalar && !VECTOR_TYPE_P (itype)));
1398 0 : internal_fn ifn = associated_internal_fn (combined_fn (code), itype);
1399 0 : return (direct_internal_fn_p (ifn)
1400 0 : && direct_internal_fn_supported_p (ifn, tree_pair (otype, itype),
1401 : OPTIMIZE_FOR_SPEED));
1402 : }
1403 :
1404 :
1405 : /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn
1406 : for a code_helper CODE operating on type TYPE. */
1407 :
1408 : internal_fn
1409 5089 : get_conditional_internal_fn (code_helper code, tree type)
1410 : {
1411 5089 : if (code.is_tree_code ())
1412 5089 : return get_conditional_internal_fn (tree_code (code));
1413 0 : auto cfn = combined_fn (code);
1414 0 : return get_conditional_internal_fn (associated_internal_fn (cfn, type));
1415 : }
1416 :
1417 : /* Find the operand which is different between ARG0_OP and ARG1_OP.
1418 : Returns the operand num where the difference is.
1419 : Set NEWARG0 and NEWARG1 from the different argument.
1420 : Returns -1 if none is found.
1421 : If ARG0_OP/ARG1_OP is commutative also try swapping the
1422 : two commutative operands and return the operand number where
1423 : the difference happens in ARG0_OP. */
1424 :
1425 : int
1426 29696 : find_different_opnum (const gimple_match_op &arg0_op,
1427 : const gimple_match_op &arg1_op,
1428 : tree *new_arg0, tree *new_arg1)
1429 : {
1430 29696 : unsigned opnum = -1;
1431 29696 : unsigned first;
1432 29696 : first = first_commutative_argument (arg1_op.code, arg1_op.type);
1433 68690 : for (unsigned i = 0; i < arg0_op.num_ops; i++)
1434 : {
1435 54437 : if (!operand_equal_for_phi_arg_p (arg0_op.ops[i],
1436 54437 : arg1_op.ops[i]))
1437 : {
1438 : /* Can handle only one non equal operand. */
1439 43158 : if (opnum != -1u)
1440 : {
1441 : /* Though if opnum is right before i and opnum is equal
1442 : to the first communtative argument, handle communtative
1443 : specially. */
1444 15443 : if (i == opnum + 1 && opnum == first)
1445 11325 : goto commutative;
1446 : return -1;
1447 : }
1448 : opnum = i;
1449 : }
1450 : }
1451 : /* If all operands are equal only do this is there was single
1452 : operand. */
1453 14253 : if (opnum == -1u)
1454 : {
1455 1981 : if (arg0_op.num_ops != 1)
1456 : return -1;
1457 : opnum = 0;
1458 : }
1459 12488 : *new_arg0 = arg0_op.ops[opnum];
1460 12488 : *new_arg1 = arg1_op.ops[opnum];
1461 12488 : return opnum;
1462 :
1463 : /* Handle commutative operations. */
1464 11325 : commutative:
1465 11325 : gcc_assert (first != -1u);
1466 :
1467 : /* Check the rest of the arguments to make sure they are the same. */
1468 11325 : for (unsigned i = first + 2; i < arg0_op.num_ops; i++)
1469 0 : if (!operand_equal_for_phi_arg_p (arg0_op.ops[i],
1470 0 : arg1_op.ops[i]))
1471 : return -1;
1472 :
1473 : /* If the arg0[first+1] and arg1[first] are the same
1474 : then the one which is different is arg0[first] and arg1[first+1]
1475 : return first since this is based on arg0. */
1476 11325 : if (operand_equal_for_phi_arg_p (arg0_op.ops[first + 1],
1477 11325 : arg1_op.ops[first]))
1478 : {
1479 76 : *new_arg0 = arg0_op.ops[first];
1480 76 : *new_arg1 = arg1_op.ops[first + 1];
1481 76 : return first;
1482 : }
1483 : /* If the arg0[first] and arg1[first+1] are the same
1484 : then the one which is different is arg0[first+1] and arg1[first]
1485 : return first+1 since this is based on arg0. */
1486 11249 : if (operand_equal_for_phi_arg_p (arg0_op.ops[first],
1487 11249 : arg1_op.ops[first + 1]))
1488 : {
1489 261 : *new_arg0 = arg0_op.ops[first + 1];
1490 261 : *new_arg1 = arg1_op.ops[first];
1491 261 : return first + 1;
1492 : }
1493 : return -1;
1494 : }
|