LCOV - code coverage report
Current view: top level - gcc - gimple-match-exports.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.3 % 561 490
Test Date: 2026-02-28 14:20:25 Functions: 91.7 % 36 33
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.