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
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
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/>. */
22 #include "coretypes.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"
39 #include "gimple-match.h"
40 #include "tree-pass.h"
41 #include "internal-fn.h"
42 #include "case-cfn-macros.h"
44 #include "optabs-tree.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
,
66 extern bool gimple_simplify (gimple_match_op
*, gimple_seq
*, tree (*)(tree
),
67 code_helper
, tree
, tree
, tree
, tree
, 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
*,
75 tree
gimple_simplify (enum tree_code
, tree
, tree
, tree
, gimple_seq
*,
77 tree
gimple_simplify (enum tree_code
, tree
, tree
, tree
, tree
, gimple_seq
*,
79 tree
gimple_simplify (combined_fn
, tree
, tree
, gimple_seq
*,
81 tree
gimple_simplify (combined_fn
, tree
, tree
, tree
, gimple_seq
*,
83 tree
gimple_simplify (combined_fn
, tree
, tree
, tree
, tree
, gimple_seq
*,
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. */
106 gimple_match_op::resimplify (gimple_seq
*seq
, tree (*valueize
)(tree
))
111 return gimple_resimplify1 (seq
, this, valueize
);
113 return gimple_resimplify2 (seq
, this, valueize
);
115 return gimple_resimplify3 (seq
, this, valueize
);
117 return gimple_resimplify4 (seq
, this, valueize
);
119 return gimple_resimplify5 (seq
, this, valueize
);
121 return gimple_resimplify6 (seq
, this, valueize
);
123 return gimple_resimplify7 (seq
, this, valueize
);
129 /* Return whether T is a constant that we'll dispatch to fold to
130 evaluate fully constant expressions. */
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. */
145 convert_conditional_op (gimple_match_op
*orig_op
,
146 gimple_match_op
*new_op
)
149 if (orig_op
->code
.is_tree_code ())
150 ifn
= get_conditional_internal_fn ((tree_code
) orig_op
->code
);
153 auto cfn
= combined_fn (orig_op
->code
);
154 if (!internal_fn_p (cfn
))
156 ifn
= get_conditional_internal_fn (as_internal_fn (cfn
));
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
);
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
;
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
;
184 /* Helper for gimple_simplify valueizing OP using VALUEIZE and setting
185 VALUEIZED to true if valueization changed OP. */
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
)
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. */
206 maybe_build_generic_op (gimple_match_op
*res_op
)
208 tree_code code
= (tree_code
) res_op
->code
;
214 case VIEW_CONVERT_EXPR
:
215 val
= build1 (code
, res_op
->type
, res_op
->ops
[0]);
216 res_op
->set_value (val
);
219 val
= build3 (code
, res_op
->type
, res_op
->ops
[0], res_op
->ops
[1],
221 REF_REVERSE_STORAGE_ORDER (val
) = res_op
->reverse
;
222 res_op
->set_value (val
);
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. */
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
,
238 if (!direct_internal_fn_supported_p (fn
, types
, OPTIMIZE_FOR_BOTH
))
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. */
259 maybe_resimplify_conditional_op (gimple_seq
*seq
, gimple_match_op
*res_op
,
260 tree (*valueize
) (tree
))
262 if (!res_op
->cond
.cond
)
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
;
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
;
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]);
290 op_could_trap
= operation_could_trap_p ((tree_code
) res_op
->code
,
291 FLOAT_TYPE_P (res_op
->type
),
293 res_op
->op_or_null (1));
297 res_op
->cond
.cond
= NULL_TREE
;
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
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
;
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
);
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
);
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
))
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. */
350 try_conditional_simplification (internal_fn ifn
, gimple_match_op
*res_op
,
351 gimple_seq
*seq
, tree (*valueize
) (tree
))
354 tree_code code
= conditional_internal_fn_code (ifn
);
355 int len_index
= internal_fn_len_index (ifn
);
356 if (code
!= ERROR_MARK
)
360 ifn
= get_unconditional_internal_fn (ifn
);
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;
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
)
382 if (!gimple_resimplify1 (seq
, &cond_op
, valueize
))
386 if (!gimple_resimplify2 (seq
, &cond_op
, valueize
))
390 if (!gimple_resimplify3 (seq
, &cond_op
, valueize
))
397 maybe_resimplify_conditional_op (seq
, res_op
, valueize
);
401 /* Helper for the autogenerated code, valueize OP. */
404 do_valueize (tree (*valueize
)(tree
), tree op
)
406 if (valueize
&& TREE_CODE (op
) == SSA_NAME
)
408 tree tem
= valueize (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. */
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
)
432 if (res_op
->code
.is_tree_code ())
435 && gimple_simplified_result_is_gimple_val (res_op
))
439 tree tem
= mprts_hook (res_op
);
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
]))
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
)))
461 if (res_op
->code
.is_tree_code ())
463 auto code
= tree_code (res_op
->code
);
466 if (gimple_in_ssa_p (cfun
))
467 res
= make_ssa_name (res_op
->type
);
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
);
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
);
494 /* Find the function we want to call. */
495 tree decl
= builtin_decl_implicit (as_builtin_fn (fn
));
499 /* We can't and should not emit calls to non-const functions. */
500 if (!(flags_from_decl_or_type (decl
) & ECF_CONST
))
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));
512 if (gimple_in_ssa_p (cfun
))
513 res
= make_ssa_name (res_op
->type
);
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
);
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. */
536 gimple_simplify (enum tree_code code
, tree type
,
538 gimple_seq
*seq
, tree (*valueize
)(tree
))
540 if (constant_for_folding (op0
))
542 tree res
= const_unop (code
, type
, op0
);
544 && CONSTANT_CLASS_P (res
))
548 gimple_match_op res_op
;
549 if (!gimple_simplify (&res_op
, seq
, valueize
, code
, type
, op0
))
551 return maybe_push_res_to_seq (&res_op
, seq
);
557 gimple_simplify (enum tree_code code
, tree type
,
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
);
565 && CONSTANT_CLASS_P (res
))
569 /* Canonicalize operand order both for matching and fallback stmt
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
))
583 return maybe_push_res_to_seq (&res_op
, seq
);
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
);
598 && CONSTANT_CLASS_P (res
))
602 /* Canonicalize operand order both for matching and fallback stmt
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
))
611 return maybe_push_res_to_seq (&res_op
, seq
);
614 /* Builtin or internal function with one argument. */
617 gimple_simplify (combined_fn fn
, tree type
,
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
))
628 gimple_match_op res_op
;
629 if (!gimple_simplify (&res_op
, seq
, valueize
, fn
, type
, arg0
))
631 return maybe_push_res_to_seq (&res_op
, seq
);
634 /* Builtin or internal function with two arguments. */
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
))
649 gimple_match_op res_op
;
650 if (!gimple_simplify (&res_op
, seq
, valueize
, fn
, type
, arg0
, arg1
))
652 return maybe_push_res_to_seq (&res_op
, seq
);
655 /* Builtin or internal function with three arguments. */
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
))
671 gimple_match_op res_op
;
672 if (!gimple_simplify (&res_op
, seq
, valueize
, fn
, type
, arg0
, arg1
, arg2
))
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
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
>
688 gimple_extract (gimple
*stmt
, gimple_match_op
*res_op
,
689 ValueizeOp valueize_op
,
690 ValueizeCondition valueize_condition
)
692 switch (gimple_code (stmt
))
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
));
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
));
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
));
726 case GIMPLE_UNARY_RHS
:
728 tree rhs1
= gimple_assign_rhs1 (stmt
);
729 res_op
->set_op (code
, type
, valueize_op (rhs1
));
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
);
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
);
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
);
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)
764 if (gimple_call_internal_p (stmt
))
765 cfn
= as_combined_fn (gimple_call_internal_fn (stmt
));
768 tree fn
= gimple_call_fn (stmt
);
772 fn
= valueize_op (fn
);
773 if (TREE_CODE (fn
) != ADDR_EXPR
774 || TREE_CODE (TREE_OPERAND (fn
, 0)) != FUNCTION_DECL
)
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
))
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
));
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
);
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. */
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. */
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
,
837 tree rhs
= do_valueize (TREE_OPERAND (op
, 1), top_valueize
,
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
)
843 && res_op2
.code
.is_tree_code ())
845 auto code
= tree_code (res_op2
.code
);
846 if (TREE_CODE_CLASS (code
) == tcc_comparison
)
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
)
857 return res_op2
.ops
[0];
860 return valueize_op (op
);
863 if (!gimple_extract (stmt
, res_op
, valueize_op
, valueize_condition
))
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
))
875 && res_op
->resimplify (seq
, valueize
))
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. */
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]);
902 tem
= fold_const_call (combined_fn (res_op
->code
), res_op
->type
,
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
);
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
;
923 if (dump_file
&& (dump_flags
& TDF_FOLDING
))
924 fprintf (dump_file
, "Aborting expression simplification due to "
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]))
940 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
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]);
969 tem
= fold_const_call (combined_fn (res_op
->code
), res_op
->type
,
970 res_op
->ops
[0], res_op
->ops
[1]);
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
);
982 /* Canonicalize operand order. */
983 bool canonicalized
= false;
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]);
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
;
1000 if (dump_file
&& (dump_flags
& TDF_FOLDING
))
1001 fprintf (dump_file
, "Aborting expression simplification due to "
1002 "deep recursion\n");
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]))
1018 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
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],
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
);
1062 /* Canonicalize operand order. */
1063 bool canonicalized
= false;
1064 int argno
= first_commutative_argument (res_op
->code
, res_op
->type
);
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
;
1076 if (dump_file
&& (dump_flags
& TDF_FOLDING
))
1077 fprintf (dump_file
, "Aborting expression simplification due to "
1078 "deep recursion\n");
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]))
1094 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
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
);
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
;
1126 if (dump_file
&& (dump_flags
& TDF_FOLDING
))
1127 fprintf (dump_file
, "Aborting expression simplification due to "
1128 "deep recursion\n");
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],
1145 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
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
);
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]))
1183 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
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
);
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]))
1221 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
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
);
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],
1260 if (maybe_resimplify_conditional_op (seq
, res_op
, valueize
))
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. */
1279 canonicalize_code (code_helper code
, tree type
)
1281 if (code
.is_fn_code ())
1282 return associated_internal_fn (combined_fn (code
), type
);
1286 /* Return true if CODE is a binary operation and if CODE is commutative when
1287 operating on type TYPE. */
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. */
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
))
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. */
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. */
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
,
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. */
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
));