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