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