ada: Fix spurious -Wstringop-overflow with link time optimization
[official-gcc.git] / gcc / gimple-match-exports.cc
blobd6dac08cc2b60cc3b3780fa1f195d4b02d5103f8
1 /* Helpers for the autogenerated gimple-match.cc file.
2 Copyright (C) 2023 Free Software Foundation, Inc.
4 This file is part of GCC.
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.
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.
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/>. */
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"
51 tree (*mprts_hook) (gimple_match_op *);
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);
70 /* Functions that are needed by gimple-match but that are exported and used in
71 other places in the compiler. */
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));
86 tree do_valueize (tree, tree (*)(tree), bool &);
87 tree do_valueize (tree (*)(tree), tree);
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. */
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));
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. */
105 bool
106 gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
108 switch (num_ops)
110 case 1:
111 return gimple_resimplify1 (seq, this, valueize);
112 case 2:
113 return gimple_resimplify2 (seq, this, valueize);
114 case 3:
115 return gimple_resimplify3 (seq, this, valueize);
116 case 4:
117 return gimple_resimplify4 (seq, this, valueize);
118 case 5:
119 return gimple_resimplify5 (seq, this, valueize);
120 case 6:
121 return gimple_resimplify6 (seq, this, valueize);
122 case 7:
123 return gimple_resimplify7 (seq, this, valueize);
124 default:
125 gcc_unreachable ();
129 /* Return whether T is a constant that we'll dispatch to fold to
130 evaluate fully constant expressions. */
132 static inline bool
133 constant_for_folding (tree t)
135 return (CONSTANT_CLASS_P (t)
136 /* The following is only interesting to string builtins. */
137 || (TREE_CODE (t) == ADDR_EXPR
138 && TREE_CODE (TREE_OPERAND (t, 0)) == STRING_CST));
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. */
144 static bool
145 convert_conditional_op (gimple_match_op *orig_op,
146 gimple_match_op *new_op)
148 internal_fn ifn;
149 if (orig_op->code.is_tree_code ())
150 ifn = get_conditional_internal_fn ((tree_code) orig_op->code);
151 else
153 auto cfn = combined_fn (orig_op->code);
154 if (!internal_fn_p (cfn))
155 return false;
156 ifn = get_conditional_internal_fn (as_internal_fn (cfn));
158 if (ifn == IFN_LAST)
159 return false;
160 unsigned int num_ops = orig_op->num_ops;
161 unsigned int num_cond_ops = 2;
162 if (orig_op->cond.len)
164 /* Add the length and bias parameters. */
165 ifn = get_len_internal_fn (ifn);
166 num_cond_ops = 4;
168 new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + num_cond_ops);
169 new_op->ops[0] = orig_op->cond.cond;
170 for (unsigned int i = 0; i < num_ops; ++i)
171 new_op->ops[i + 1] = orig_op->ops[i];
172 tree else_value = orig_op->cond.else_value;
173 if (!else_value)
174 else_value = targetm.preferred_else_value (ifn, orig_op->type,
175 num_ops, orig_op->ops);
176 new_op->ops[num_ops + 1] = else_value;
177 if (orig_op->cond.len)
179 new_op->ops[num_ops + 2] = orig_op->cond.len;
180 new_op->ops[num_ops + 3] = orig_op->cond.bias;
182 return true;
184 /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
185 VALUEIZED to true if valueization changed OP. */
187 inline tree
188 do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
190 if (valueize && TREE_CODE (op) == SSA_NAME)
192 tree tem = valueize (op);
193 if (tem && tem != op)
195 op = tem;
196 valueized = true;
199 return op;
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. */
205 void
206 maybe_build_generic_op (gimple_match_op *res_op)
208 tree_code code = (tree_code) res_op->code;
209 tree val;
210 switch (code)
212 case REALPART_EXPR:
213 case IMAGPART_EXPR:
214 case VIEW_CONVERT_EXPR:
215 val = build1 (code, res_op->type, res_op->ops[0]);
216 res_op->set_value (val);
217 break;
218 case BIT_FIELD_REF:
219 val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
220 res_op->ops[2]);
221 REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
222 res_op->set_value (val);
223 break;
224 default:;
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. */
231 static gcall *
232 build_call_internal (internal_fn fn, gimple_match_op *res_op)
234 if (direct_internal_fn_p (fn))
236 tree_pair types = direct_internal_fn_types (fn, res_op->type,
237 res_op->ops);
238 if (!direct_internal_fn_supported_p (fn, types, OPTIMIZE_FOR_BOTH))
239 return NULL;
241 return gimple_build_call_internal (fn, res_op->num_ops,
242 res_op->op_or_null (0),
243 res_op->op_or_null (1),
244 res_op->op_or_null (2),
245 res_op->op_or_null (3),
246 res_op->op_or_null (4),
247 res_op->op_or_null (5),
248 res_op->op_or_null (6));
251 /* RES_OP is the result of a simplification. If it is conditional,
252 try to replace it with the equivalent UNCOND form, such as an
253 IFN_COND_* call or a VEC_COND_EXPR. Also try to resimplify the
254 result of the replacement if appropriate, adding any new statements to
255 SEQ and using VALUEIZE as the valueization function. Return true if
256 this resimplification occurred and resulted in at least one change. */
258 static bool
259 maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
260 tree (*valueize) (tree))
262 if (!res_op->cond.cond)
263 return false;
265 if (!res_op->cond.else_value
266 && res_op->code.is_tree_code ())
268 /* The "else" value doesn't matter. If the "then" value is a
269 gimple value, just use it unconditionally. This isn't a
270 simplification in itself, since there was no operation to
271 build in the first place. */
272 if (gimple_simplified_result_is_gimple_val (res_op))
274 res_op->cond.cond = NULL_TREE;
275 return false;
278 /* Likewise if the operation would not trap. */
279 bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
280 && TYPE_OVERFLOW_TRAPS (res_op->type));
281 tree_code op_code = (tree_code) res_op->code;
282 bool op_could_trap;
284 /* COND_EXPR will trap if, and only if, the condition
285 traps and hence we have to check this. For all other operations, we
286 don't need to consider the operands. */
287 if (op_code == COND_EXPR)
288 op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
289 else
290 op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
291 FLOAT_TYPE_P (res_op->type),
292 honor_trapv,
293 res_op->op_or_null (1));
295 if (!op_could_trap)
297 res_op->cond.cond = NULL_TREE;
298 return false;
302 /* If the "then" value is a gimple value and the "else" value matters,
303 create a VEC_COND_EXPR between them, then see if it can be further
304 simplified. */
305 gimple_match_op new_op;
306 if (res_op->cond.else_value
307 && VECTOR_TYPE_P (res_op->type)
308 && gimple_simplified_result_is_gimple_val (res_op))
310 tree len = res_op->cond.len;
311 if (!len)
312 new_op.set_op (VEC_COND_EXPR, res_op->type,
313 res_op->cond.cond, res_op->ops[0],
314 res_op->cond.else_value);
315 else
316 new_op.set_op (IFN_VCOND_MASK_LEN, res_op->type,
317 res_op->cond.cond, res_op->ops[0],
318 res_op->cond.else_value,
319 res_op->cond.len, res_op->cond.bias);
320 *res_op = new_op;
321 return gimple_resimplify3 (seq, res_op, valueize);
324 /* Otherwise try rewriting the operation as an IFN_COND_* call.
325 Again, this isn't a simplification in itself, since it's what
326 RES_OP already described. */
327 if (convert_conditional_op (res_op, &new_op))
328 *res_op = new_op;
330 return false;
333 /* If RES_OP is a call to a conditional internal function, try simplifying
334 the associated unconditional operation and using the result to build
335 a new conditional operation. For example, if RES_OP is:
337 IFN_COND_ADD (COND, A, B, ELSE)
339 try simplifying (plus A B) and using the result to build a replacement
340 for the whole IFN_COND_ADD.
342 Return true if this approach led to a simplification, otherwise leave
343 RES_OP unchanged (and so suitable for other simplifications). When
344 returning true, add any new statements to SEQ and use VALUEIZE as the
345 valueization function.
347 RES_OP is known to be a call to IFN. */
349 static bool
350 try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
351 gimple_seq *seq, tree (*valueize) (tree))
353 code_helper op;
354 tree_code code = conditional_internal_fn_code (ifn);
355 int len_index = internal_fn_len_index (ifn);
356 if (code != ERROR_MARK)
357 op = code;
358 else
360 ifn = get_unconditional_internal_fn (ifn);
361 if (ifn == IFN_LAST)
362 return false;
363 op = as_combined_fn (ifn);
366 unsigned int num_ops = res_op->num_ops;
367 /* num_cond_ops = 2 for COND_ADD (MASK and ELSE)
368 wheras num_cond_ops = 4 for COND_LEN_ADD (MASK, ELSE, LEN and BIAS). */
369 unsigned int num_cond_ops = len_index < 0 ? 2 : 4;
370 tree else_value
371 = len_index < 0 ? res_op->ops[num_ops - 1] : res_op->ops[num_ops - 3];
372 tree len = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 2];
373 tree bias = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 1];
374 gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
375 else_value, len, bias),
376 op, res_op->type, num_ops - num_cond_ops);
378 memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
379 switch (num_ops - num_cond_ops)
381 case 1:
382 if (!gimple_resimplify1 (seq, &cond_op, valueize))
383 return false;
384 break;
385 case 2:
386 if (!gimple_resimplify2 (seq, &cond_op, valueize))
387 return false;
388 break;
389 case 3:
390 if (!gimple_resimplify3 (seq, &cond_op, valueize))
391 return false;
392 break;
393 default:
394 gcc_unreachable ();
396 *res_op = cond_op;
397 maybe_resimplify_conditional_op (seq, res_op, valueize);
398 return true;
401 /* Helper for the autogenerated code, valueize OP. */
403 tree
404 do_valueize (tree (*valueize)(tree), tree op)
406 if (valueize && TREE_CODE (op) == SSA_NAME)
408 tree tem = valueize (op);
409 if (tem)
410 return tem;
412 return op;
415 /* Push the exploded expression described by RES_OP as a statement to
416 SEQ if necessary and return a gimple value denoting the value of the
417 expression. If RES is not NULL then the result will be always RES
418 and even gimple values are pushed to SEQ. */
420 tree
421 maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
423 tree *ops = res_op->ops;
424 unsigned num_ops = res_op->num_ops;
426 /* The caller should have converted conditional operations into an UNCOND
427 form and resimplified as appropriate. The conditional form only
428 survives this far if that conversion failed. */
429 if (res_op->cond.cond)
430 return NULL_TREE;
432 if (res_op->code.is_tree_code ())
434 if (!res
435 && gimple_simplified_result_is_gimple_val (res_op))
436 return ops[0];
437 if (mprts_hook)
439 tree tem = mprts_hook (res_op);
440 if (tem)
441 return tem;
445 if (!seq)
446 return NULL_TREE;
448 /* Play safe and do not allow abnormals to be mentioned in
449 newly created statements. */
450 for (unsigned int i = 0; i < num_ops; ++i)
451 if (TREE_CODE (ops[i]) == SSA_NAME
452 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
453 return NULL_TREE;
455 if (num_ops > 0 && COMPARISON_CLASS_P (ops[0]))
456 for (unsigned int i = 0; i < 2; ++i)
457 if (TREE_CODE (TREE_OPERAND (ops[0], i)) == SSA_NAME
458 && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (TREE_OPERAND (ops[0], i)))
459 return NULL_TREE;
461 if (res_op->code.is_tree_code ())
463 auto code = tree_code (res_op->code);
464 if (!res)
466 if (gimple_in_ssa_p (cfun))
467 res = make_ssa_name (res_op->type);
468 else
469 res = create_tmp_reg (res_op->type);
471 maybe_build_generic_op (res_op);
472 gimple *new_stmt = gimple_build_assign (res, code,
473 res_op->op_or_null (0),
474 res_op->op_or_null (1),
475 res_op->op_or_null (2));
476 gimple_seq_add_stmt_without_update (seq, new_stmt);
477 return res;
479 else
481 gcc_assert (num_ops != 0);
482 auto fn = combined_fn (res_op->code);
483 gcall *new_stmt = NULL;
484 if (internal_fn_p (fn))
486 /* Generate the given function if we can. */
487 internal_fn ifn = as_internal_fn (fn);
488 new_stmt = build_call_internal (ifn, res_op);
489 if (!new_stmt)
490 return NULL_TREE;
492 else
494 /* Find the function we want to call. */
495 tree decl = builtin_decl_implicit (as_builtin_fn (fn));
496 if (!decl)
497 return NULL;
499 /* We can't and should not emit calls to non-const functions. */
500 if (!(flags_from_decl_or_type (decl) & ECF_CONST))
501 return NULL;
503 new_stmt = gimple_build_call (decl, num_ops,
504 res_op->op_or_null (0),
505 res_op->op_or_null (1),
506 res_op->op_or_null (2),
507 res_op->op_or_null (3),
508 res_op->op_or_null (4));
510 if (!res)
512 if (gimple_in_ssa_p (cfun))
513 res = make_ssa_name (res_op->type);
514 else
515 res = create_tmp_reg (res_op->type);
517 gimple_call_set_lhs (new_stmt, res);
518 gimple_seq_add_stmt_without_update (seq, new_stmt);
519 return res;
524 /* Public API overloads follow for operation being tree_code or
525 built_in_function and for one to three operands or arguments.
526 They return NULL_TREE if nothing could be simplified or
527 the resulting simplified value with parts pushed to SEQ.
528 If SEQ is NULL then if the simplification needs to create
529 new stmts it will fail. If VALUEIZE is non-NULL then all
530 SSA names will be valueized using that hook prior to
531 applying simplifications. */
533 /* Unary ops. */
535 tree
536 gimple_simplify (enum tree_code code, tree type,
537 tree op0,
538 gimple_seq *seq, tree (*valueize)(tree))
540 if (constant_for_folding (op0))
542 tree res = const_unop (code, type, op0);
543 if (res != NULL_TREE
544 && CONSTANT_CLASS_P (res))
545 return res;
548 gimple_match_op res_op;
549 if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
550 return NULL_TREE;
551 return maybe_push_res_to_seq (&res_op, seq);
554 /* Binary ops. */
556 tree
557 gimple_simplify (enum tree_code code, tree type,
558 tree op0, tree op1,
559 gimple_seq *seq, tree (*valueize)(tree))
561 if (constant_for_folding (op0) && constant_for_folding (op1))
563 tree res = const_binop (code, type, op0, op1);
564 if (res != NULL_TREE
565 && CONSTANT_CLASS_P (res))
566 return res;
569 /* Canonicalize operand order both for matching and fallback stmt
570 generation. */
571 if ((commutative_tree_code (code)
572 || TREE_CODE_CLASS (code) == tcc_comparison)
573 && tree_swap_operands_p (op0, op1))
575 std::swap (op0, op1);
576 if (TREE_CODE_CLASS (code) == tcc_comparison)
577 code = swap_tree_comparison (code);
580 gimple_match_op res_op;
581 if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
582 return NULL_TREE;
583 return maybe_push_res_to_seq (&res_op, seq);
586 /* Ternary ops. */
588 tree
589 gimple_simplify (enum tree_code code, tree type,
590 tree op0, tree op1, tree op2,
591 gimple_seq *seq, tree (*valueize)(tree))
593 if (constant_for_folding (op0) && constant_for_folding (op1)
594 && constant_for_folding (op2))
596 tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
597 if (res != NULL_TREE
598 && CONSTANT_CLASS_P (res))
599 return res;
602 /* Canonicalize operand order both for matching and fallback stmt
603 generation. */
604 if (commutative_ternary_tree_code (code)
605 && tree_swap_operands_p (op0, op1))
606 std::swap (op0, op1);
608 gimple_match_op res_op;
609 if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
610 return NULL_TREE;
611 return maybe_push_res_to_seq (&res_op, seq);
614 /* Builtin or internal function with one argument. */
616 tree
617 gimple_simplify (combined_fn fn, tree type,
618 tree arg0,
619 gimple_seq *seq, tree (*valueize)(tree))
621 if (constant_for_folding (arg0))
623 tree res = fold_const_call (fn, type, arg0);
624 if (res && CONSTANT_CLASS_P (res))
625 return res;
628 gimple_match_op res_op;
629 if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
630 return NULL_TREE;
631 return maybe_push_res_to_seq (&res_op, seq);
634 /* Builtin or internal function with two arguments. */
636 tree
637 gimple_simplify (combined_fn fn, tree type,
638 tree arg0, tree arg1,
639 gimple_seq *seq, tree (*valueize)(tree))
641 if (constant_for_folding (arg0)
642 && constant_for_folding (arg1))
644 tree res = fold_const_call (fn, type, arg0, arg1);
645 if (res && CONSTANT_CLASS_P (res))
646 return res;
649 gimple_match_op res_op;
650 if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
651 return NULL_TREE;
652 return maybe_push_res_to_seq (&res_op, seq);
655 /* Builtin or internal function with three arguments. */
657 tree
658 gimple_simplify (combined_fn fn, tree type,
659 tree arg0, tree arg1, tree arg2,
660 gimple_seq *seq, tree (*valueize)(tree))
662 if (constant_for_folding (arg0)
663 && constant_for_folding (arg1)
664 && constant_for_folding (arg2))
666 tree res = fold_const_call (fn, type, arg0, arg1, arg2);
667 if (res && CONSTANT_CLASS_P (res))
668 return res;
671 gimple_match_op res_op;
672 if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
673 return NULL_TREE;
674 return maybe_push_res_to_seq (&res_op, seq);
677 /* Common subroutine of gimple_extract_op and gimple_simplify. Try to
678 describe STMT in RES_OP, returning true on success. Before recording
679 an operand, call:
681 - VALUEIZE_CONDITION for a COND_EXPR condition
682 - VALUEIZE_OP for every other top-level operand
684 Both routines take a tree argument and returns a tree. */
686 template<typename ValueizeOp, typename ValueizeCondition>
687 inline bool
688 gimple_extract (gimple *stmt, gimple_match_op *res_op,
689 ValueizeOp valueize_op,
690 ValueizeCondition valueize_condition)
692 switch (gimple_code (stmt))
694 case GIMPLE_ASSIGN:
696 enum tree_code code = gimple_assign_rhs_code (stmt);
697 tree type = TREE_TYPE (gimple_assign_lhs (stmt));
698 switch (gimple_assign_rhs_class (stmt))
700 case GIMPLE_SINGLE_RHS:
701 if (code == REALPART_EXPR
702 || code == IMAGPART_EXPR
703 || code == VIEW_CONVERT_EXPR)
705 tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
706 res_op->set_op (code, type, valueize_op (op0));
707 return true;
709 else if (code == BIT_FIELD_REF)
711 tree rhs1 = gimple_assign_rhs1 (stmt);
712 tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
713 res_op->set_op (code, type, op0,
714 TREE_OPERAND (rhs1, 1),
715 TREE_OPERAND (rhs1, 2),
716 REF_REVERSE_STORAGE_ORDER (rhs1));
717 return true;
719 else if (code == SSA_NAME)
721 tree op0 = gimple_assign_rhs1 (stmt);
722 res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
723 return true;
725 break;
726 case GIMPLE_UNARY_RHS:
728 tree rhs1 = gimple_assign_rhs1 (stmt);
729 res_op->set_op (code, type, valueize_op (rhs1));
730 return true;
732 case GIMPLE_BINARY_RHS:
734 tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
735 tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
736 res_op->set_op (code, type, rhs1, rhs2);
737 return true;
739 case GIMPLE_TERNARY_RHS:
741 tree rhs1 = gimple_assign_rhs1 (stmt);
742 if (code == COND_EXPR && COMPARISON_CLASS_P (rhs1))
743 rhs1 = valueize_condition (rhs1);
744 else
745 rhs1 = valueize_op (rhs1);
746 tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
747 tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
748 res_op->set_op (code, type, rhs1, rhs2, rhs3);
749 return true;
751 default:
752 gcc_unreachable ();
754 break;
757 case GIMPLE_CALL:
758 /* ??? This way we can't simplify calls with side-effects. */
759 if (gimple_call_lhs (stmt) != NULL_TREE
760 && gimple_call_num_args (stmt) >= 1
761 && gimple_call_num_args (stmt) <= 7)
763 combined_fn cfn;
764 if (gimple_call_internal_p (stmt))
765 cfn = as_combined_fn (gimple_call_internal_fn (stmt));
766 else
768 tree fn = gimple_call_fn (stmt);
769 if (!fn)
770 return false;
772 fn = valueize_op (fn);
773 if (TREE_CODE (fn) != ADDR_EXPR
774 || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
775 return false;
777 tree decl = TREE_OPERAND (fn, 0);
778 if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
779 || !gimple_builtin_call_types_compatible_p (stmt, decl))
780 return false;
782 cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
785 unsigned int num_args = gimple_call_num_args (stmt);
786 res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
787 for (unsigned i = 0; i < num_args; ++i)
788 res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
789 return true;
791 break;
793 case GIMPLE_COND:
795 tree lhs = valueize_op (gimple_cond_lhs (stmt));
796 tree rhs = valueize_op (gimple_cond_rhs (stmt));
797 res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
798 return true;
801 default:
802 break;
805 return false;
808 /* Try to describe STMT in RES_OP, returning true on success.
809 For GIMPLE_CONDs, describe the condition that is being tested.
810 For GIMPLE_ASSIGNs, describe the rhs of the assignment.
811 For GIMPLE_CALLs, describe the call. */
813 bool
814 gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
816 auto nop = [](tree op) { return op; };
817 return gimple_extract (stmt, res_op, nop, nop);
820 /* The main STMT based simplification entry. It is used by the fold_stmt
821 and the fold_stmt_to_constant APIs. */
823 bool
824 gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
825 tree (*valueize)(tree), tree (*top_valueize)(tree))
827 bool valueized = false;
828 auto valueize_op = [&](tree op)
830 return do_valueize (op, top_valueize, valueized);
832 auto valueize_condition = [&](tree op) -> tree
834 bool cond_valueized = false;
835 tree lhs = do_valueize (TREE_OPERAND (op, 0), top_valueize,
836 cond_valueized);
837 tree rhs = do_valueize (TREE_OPERAND (op, 1), top_valueize,
838 cond_valueized);
839 gimple_match_op res_op2 (res_op->cond, TREE_CODE (op),
840 TREE_TYPE (op), lhs, rhs);
841 if ((gimple_resimplify2 (seq, &res_op2, valueize)
842 || cond_valueized)
843 && res_op2.code.is_tree_code ())
845 auto code = tree_code (res_op2.code);
846 if (TREE_CODE_CLASS (code) == tcc_comparison)
848 valueized = true;
849 return build2 (code, TREE_TYPE (op),
850 res_op2.ops[0], res_op2.ops[1]);
852 else if (code == SSA_NAME
853 || code == INTEGER_CST
854 || code == VECTOR_CST)
856 valueized = true;
857 return res_op2.ops[0];
860 return valueize_op (op);
863 if (!gimple_extract (stmt, res_op, valueize_op, valueize_condition))
864 return false;
866 if (res_op->code.is_internal_fn ())
868 internal_fn ifn = internal_fn (res_op->code);
869 if (try_conditional_simplification (ifn, res_op, seq, valueize))
870 return true;
873 if (!res_op->reverse
874 && res_op->num_ops
875 && res_op->resimplify (seq, valueize))
876 return true;
878 return valueized;
881 /* Helper that matches and simplifies the toplevel result from
882 a gimple_simplify run (where we don't want to build
883 a stmt in case it's used in in-place folding). Replaces
884 RES_OP with a simplified and/or canonicalized result and
885 returns whether any change was made. */
887 static bool
888 gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
889 tree (*valueize)(tree))
891 if (constant_for_folding (res_op->ops[0]))
893 tree tem = NULL_TREE;
894 if (res_op->code.is_tree_code ())
896 auto code = tree_code (res_op->code);
897 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
898 && TREE_CODE_LENGTH (code) == 1)
899 tem = const_unop (code, res_op->type, res_op->ops[0]);
901 else
902 tem = fold_const_call (combined_fn (res_op->code), res_op->type,
903 res_op->ops[0]);
904 if (tem != NULL_TREE
905 && CONSTANT_CLASS_P (tem))
907 if (TREE_OVERFLOW_P (tem))
908 tem = drop_tree_overflow (tem);
909 res_op->set_value (tem);
910 maybe_resimplify_conditional_op (seq, res_op, valueize);
911 return true;
915 /* Limit recursion, there are cases like PR80887 and others, for
916 example when value-numbering presents us with unfolded expressions
917 that we are really not prepared to handle without eventual
918 oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
919 itself as available expression. */
920 static unsigned depth;
921 if (depth > 10)
923 if (dump_file && (dump_flags & TDF_FOLDING))
924 fprintf (dump_file, "Aborting expression simplification due to "
925 "deep recursion\n");
926 return false;
929 ++depth;
930 gimple_match_op res_op2 (*res_op);
931 if (gimple_simplify (&res_op2, seq, valueize,
932 res_op->code, res_op->type, res_op->ops[0]))
934 --depth;
935 *res_op = res_op2;
936 return true;
938 --depth;
940 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
941 return true;
943 return false;
946 /* Helper that matches and simplifies the toplevel result from
947 a gimple_simplify run (where we don't want to build
948 a stmt in case it's used in in-place folding). Replaces
949 RES_OP with a simplified and/or canonicalized result and
950 returns whether any change was made. */
952 static bool
953 gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
954 tree (*valueize)(tree))
956 if (constant_for_folding (res_op->ops[0])
957 && constant_for_folding (res_op->ops[1]))
959 tree tem = NULL_TREE;
960 if (res_op->code.is_tree_code ())
962 auto code = tree_code (res_op->code);
963 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
964 && TREE_CODE_LENGTH (code) == 2)
965 tem = const_binop (code, res_op->type,
966 res_op->ops[0], res_op->ops[1]);
968 else
969 tem = fold_const_call (combined_fn (res_op->code), res_op->type,
970 res_op->ops[0], res_op->ops[1]);
971 if (tem != NULL_TREE
972 && CONSTANT_CLASS_P (tem))
974 if (TREE_OVERFLOW_P (tem))
975 tem = drop_tree_overflow (tem);
976 res_op->set_value (tem);
977 maybe_resimplify_conditional_op (seq, res_op, valueize);
978 return true;
982 /* Canonicalize operand order. */
983 bool canonicalized = false;
984 bool is_comparison
985 = (res_op->code.is_tree_code ()
986 && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison);
987 if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type))
988 && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
990 std::swap (res_op->ops[0], res_op->ops[1]);
991 if (is_comparison)
992 res_op->code = swap_tree_comparison (tree_code (res_op->code));
993 canonicalized = true;
996 /* Limit recursion, see gimple_resimplify1. */
997 static unsigned depth;
998 if (depth > 10)
1000 if (dump_file && (dump_flags & TDF_FOLDING))
1001 fprintf (dump_file, "Aborting expression simplification due to "
1002 "deep recursion\n");
1003 return false;
1006 ++depth;
1007 gimple_match_op res_op2 (*res_op);
1008 if (gimple_simplify (&res_op2, seq, valueize,
1009 res_op->code, res_op->type,
1010 res_op->ops[0], res_op->ops[1]))
1012 --depth;
1013 *res_op = res_op2;
1014 return true;
1016 --depth;
1018 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1019 return true;
1021 return canonicalized;
1024 /* Helper that matches and simplifies the toplevel result from
1025 a gimple_simplify run (where we don't want to build
1026 a stmt in case it's used in in-place folding). Replaces
1027 RES_OP with a simplified and/or canonicalized result and
1028 returns whether any change was made. */
1030 static bool
1031 gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
1032 tree (*valueize)(tree))
1034 if (constant_for_folding (res_op->ops[0])
1035 && constant_for_folding (res_op->ops[1])
1036 && constant_for_folding (res_op->ops[2]))
1038 tree tem = NULL_TREE;
1039 if (res_op->code.is_tree_code ())
1041 auto code = tree_code (res_op->code);
1042 if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
1043 && TREE_CODE_LENGTH (code) == 3)
1044 tem = fold_ternary/*_to_constant*/ (code, res_op->type,
1045 res_op->ops[0], res_op->ops[1],
1046 res_op->ops[2]);
1048 else
1049 tem = fold_const_call (combined_fn (res_op->code), res_op->type,
1050 res_op->ops[0], res_op->ops[1], res_op->ops[2]);
1051 if (tem != NULL_TREE
1052 && CONSTANT_CLASS_P (tem))
1054 if (TREE_OVERFLOW_P (tem))
1055 tem = drop_tree_overflow (tem);
1056 res_op->set_value (tem);
1057 maybe_resimplify_conditional_op (seq, res_op, valueize);
1058 return true;
1062 /* Canonicalize operand order. */
1063 bool canonicalized = false;
1064 int argno = first_commutative_argument (res_op->code, res_op->type);
1065 if (argno >= 0
1066 && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1068 std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1069 canonicalized = true;
1072 /* Limit recursion, see gimple_resimplify1. */
1073 static unsigned depth;
1074 if (depth > 10)
1076 if (dump_file && (dump_flags & TDF_FOLDING))
1077 fprintf (dump_file, "Aborting expression simplification due to "
1078 "deep recursion\n");
1079 return false;
1082 ++depth;
1083 gimple_match_op res_op2 (*res_op);
1084 if (gimple_simplify (&res_op2, seq, valueize,
1085 res_op->code, res_op->type,
1086 res_op->ops[0], res_op->ops[1], res_op->ops[2]))
1088 --depth;
1089 *res_op = res_op2;
1090 return true;
1092 --depth;
1094 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1095 return true;
1097 return canonicalized;
1100 /* Helper that matches and simplifies the toplevel result from
1101 a gimple_simplify run (where we don't want to build
1102 a stmt in case it's used in in-place folding). Replaces
1103 RES_OP with a simplified and/or canonicalized result and
1104 returns whether any change was made. */
1106 static bool
1107 gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
1108 tree (*valueize)(tree))
1110 /* No constant folding is defined for four-operand functions. */
1112 /* Canonicalize operand order. */
1113 bool canonicalized = false;
1114 int argno = first_commutative_argument (res_op->code, res_op->type);
1115 if (argno >= 0
1116 && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1118 std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1119 canonicalized = true;
1122 /* Limit recursion, see gimple_resimplify1. */
1123 static unsigned depth;
1124 if (depth > 10)
1126 if (dump_file && (dump_flags & TDF_FOLDING))
1127 fprintf (dump_file, "Aborting expression simplification due to "
1128 "deep recursion\n");
1129 return false;
1132 ++depth;
1133 gimple_match_op res_op2 (*res_op);
1134 if (gimple_simplify (&res_op2, seq, valueize,
1135 res_op->code, res_op->type,
1136 res_op->ops[0], res_op->ops[1], res_op->ops[2],
1137 res_op->ops[3]))
1139 --depth;
1140 *res_op = res_op2;
1141 return true;
1143 --depth;
1145 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1146 return true;
1148 return canonicalized;
1151 /* Helper that matches and simplifies the toplevel result from
1152 a gimple_simplify run (where we don't want to build
1153 a stmt in case it's used in in-place folding). Replaces
1154 RES_OP with a simplified and/or canonicalized result and
1155 returns whether any change was made. */
1157 static bool
1158 gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
1159 tree (*valueize)(tree))
1161 /* No constant folding is defined for five-operand functions. */
1163 /* Canonicalize operand order. */
1164 bool canonicalized = false;
1165 int argno = first_commutative_argument (res_op->code, res_op->type);
1166 if (argno >= 0
1167 && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1169 std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1170 canonicalized = true;
1173 gimple_match_op res_op2 (*res_op);
1174 if (gimple_simplify (&res_op2, seq, valueize,
1175 res_op->code, res_op->type,
1176 res_op->ops[0], res_op->ops[1], res_op->ops[2],
1177 res_op->ops[3], res_op->ops[4]))
1179 *res_op = res_op2;
1180 return true;
1183 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1184 return true;
1186 return canonicalized;
1189 /* Helper that matches and simplifies the toplevel result from
1190 a gimple_simplify run (where we don't want to build
1191 a stmt in case it's used in in-place folding). Replaces
1192 RES_OP with a simplified and/or canonicalized result and
1193 returns whether any change was made. */
1195 static bool
1196 gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
1197 tree (*valueize)(tree))
1199 /* No constant folding is defined for six-operand functions. */
1201 /* Canonicalize operand order. */
1202 bool canonicalized = false;
1203 int argno = first_commutative_argument (res_op->code, res_op->type);
1204 if (argno >= 0
1205 && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1207 std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1208 canonicalized = true;
1211 gimple_match_op res_op2 (*res_op);
1212 if (gimple_simplify (&res_op2, seq, valueize,
1213 res_op->code, res_op->type,
1214 res_op->ops[0], res_op->ops[1], res_op->ops[2],
1215 res_op->ops[3], res_op->ops[4], res_op->ops[5]))
1217 *res_op = res_op2;
1218 return true;
1221 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1222 return true;
1224 return canonicalized;
1227 /* Helper that matches and simplifies the toplevel result from
1228 a gimple_simplify run (where we don't want to build
1229 a stmt in case it's used in in-place folding). Replaces
1230 RES_OP with a simplified and/or canonicalized result and
1231 returns whether any change was made. */
1233 static bool
1234 gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
1235 tree (*valueize)(tree))
1237 /* No constant folding is defined for seven-operand functions. */
1239 /* Canonicalize operand order. */
1240 bool canonicalized = false;
1241 int argno = first_commutative_argument (res_op->code, res_op->type);
1242 if (argno >= 0
1243 && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
1245 std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
1246 canonicalized = true;
1249 gimple_match_op res_op2 (*res_op);
1250 if (gimple_simplify (&res_op2, seq, valueize,
1251 res_op->code, res_op->type,
1252 res_op->ops[0], res_op->ops[1], res_op->ops[2],
1253 res_op->ops[3], res_op->ops[4], res_op->ops[5],
1254 res_op->ops[6]))
1256 *res_op = res_op2;
1257 return true;
1260 if (maybe_resimplify_conditional_op (seq, res_op, valueize))
1261 return true;
1263 return canonicalized;
1266 /* Return a canonical form for CODE when operating on TYPE. The idea
1267 is to remove redundant ways of representing the same operation so
1268 that code_helpers can be hashed and compared for equality.
1270 The only current canonicalization is to replace built-in functions
1271 with internal functions, in cases where internal-fn.def defines
1272 such an internal function.
1274 Note that the new code_helper cannot necessarily be used in place of
1275 the original code_helper. For example, the new code_helper might be
1276 an internal function that the target does not support. */
1278 code_helper
1279 canonicalize_code (code_helper code, tree type)
1281 if (code.is_fn_code ())
1282 return associated_internal_fn (combined_fn (code), type);
1283 return code;
1286 /* Return true if CODE is a binary operation and if CODE is commutative when
1287 operating on type TYPE. */
1289 bool
1290 commutative_binary_op_p (code_helper code, tree type)
1292 if (code.is_tree_code ())
1293 return commutative_tree_code (tree_code (code));
1294 auto cfn = combined_fn (code);
1295 return commutative_binary_fn_p (associated_internal_fn (cfn, type));
1298 /* Return true if CODE represents a ternary operation and if the first two
1299 operands are commutative when CODE is operating on TYPE. */
1301 bool
1302 commutative_ternary_op_p (code_helper code, tree type)
1304 if (code.is_tree_code ())
1305 return commutative_ternary_tree_code (tree_code (code));
1306 auto cfn = combined_fn (code);
1307 return commutative_ternary_fn_p (associated_internal_fn (cfn, type));
1310 /* If CODE is commutative in two consecutive operands, return the
1311 index of the first, otherwise return -1. */
1314 first_commutative_argument (code_helper code, tree type)
1316 if (code.is_tree_code ())
1318 auto tcode = tree_code (code);
1319 if (commutative_tree_code (tcode)
1320 || commutative_ternary_tree_code (tcode))
1321 return 0;
1322 return -1;
1324 auto cfn = combined_fn (code);
1325 return first_commutative_argument (associated_internal_fn (cfn, type));
1328 /* Return true if CODE is a binary operation that is associative when
1329 operating on type TYPE. */
1331 bool
1332 associative_binary_op_p (code_helper code, tree type)
1334 if (code.is_tree_code ())
1335 return associative_tree_code (tree_code (code));
1336 auto cfn = combined_fn (code);
1337 return associative_binary_fn_p (associated_internal_fn (cfn, type));
1340 /* Return true if the target directly supports operation CODE on type TYPE.
1341 QUERY_TYPE acts as for optab_for_tree_code. */
1343 bool
1344 directly_supported_p (code_helper code, tree type, optab_subtype query_type)
1346 if (code.is_tree_code ())
1348 direct_optab optab = optab_for_tree_code (tree_code (code), type,
1349 query_type);
1350 return (optab != unknown_optab
1351 && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing);
1353 gcc_assert (query_type == optab_default
1354 || (query_type == optab_vector && VECTOR_TYPE_P (type))
1355 || (query_type == optab_scalar && !VECTOR_TYPE_P (type)));
1356 internal_fn ifn = associated_internal_fn (combined_fn (code), type);
1357 return (direct_internal_fn_p (ifn)
1358 && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
1361 /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn
1362 for a code_helper CODE operating on type TYPE. */
1364 internal_fn
1365 get_conditional_internal_fn (code_helper code, tree type)
1367 if (code.is_tree_code ())
1368 return get_conditional_internal_fn (tree_code (code));
1369 auto cfn = combined_fn (code);
1370 return get_conditional_internal_fn (associated_internal_fn (cfn, type));