LCOV - code coverage report
Current view: top level - gcc - gimple-match-exports.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.7 % 593 520
Test Date: 2026-06-20 15:32:29 Functions: 91.9 % 37 34
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    678467456 : gimple_match_op::resimplify (gimple_seq *seq, tree (*valueize)(tree))
     107              : {
     108    678467456 :   switch (num_ops)
     109              :     {
     110    153910495 :     case 1:
     111    153910495 :       return gimple_resimplify1 (seq, this, valueize);
     112    516313374 :     case 2:
     113    516313374 :       return gimple_resimplify2 (seq, this, valueize);
     114      7284377 :     case 3:
     115      7284377 :       return gimple_resimplify3 (seq, this, valueize);
     116       246321 :     case 4:
     117       246321 :       return gimple_resimplify4 (seq, this, valueize);
     118        24815 :     case 5:
     119        24815 :       return gimple_resimplify5 (seq, this, valueize);
     120       604003 :     case 6:
     121       604003 :       return gimple_resimplify6 (seq, this, valueize);
     122        84071 :     case 7:
     123        84071 :       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       633249 : gimple_match_op::operands_occurs_in_abnormal_phi() const
     133              : {
     134      1776112 :   for (unsigned int i = 0; i < num_ops; i++)
     135              :     {
     136      1142865 :        if (TREE_CODE (ops[i]) == SSA_NAME
     137      1142865 :            && 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    735984558 : constant_for_folding (tree t)
     148              : {
     149    735984558 :   return (CONSTANT_CLASS_P (t)
     150              :           /* The following is only interesting to string builtins.  */
     151    735984558 :           || (TREE_CODE (t) == ADDR_EXPR
     152     13653472 :               && 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        12720 : convert_conditional_op (gimple_match_op *orig_op,
     160              :                         gimple_match_op *new_op)
     161              : {
     162        12720 :   internal_fn ifn;
     163        12720 :   if (orig_op->code.is_tree_code ())
     164        11570 :     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        12720 :   if (ifn == IFN_LAST)
     173              :     return false;
     174        11130 :   unsigned int num_ops = orig_op->num_ops;
     175        11130 :   unsigned int num_cond_ops = 2;
     176        11130 :   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        11130 :   new_op->set_op (as_combined_fn (ifn), orig_op->type, num_ops + num_cond_ops);
     183        11130 :   new_op->ops[0] = orig_op->cond.cond;
     184        34534 :   for (unsigned int i = 0; i < num_ops; ++i)
     185        23404 :     new_op->ops[i + 1] = orig_op->ops[i];
     186        11130 :   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        11130 :   if (else_value
     191        11130 :       && !types_compatible_p (orig_op->type, TREE_TYPE (else_value)))
     192              :     return false;
     193              : 
     194        11130 :   if (!else_value)
     195            6 :     else_value = targetm.preferred_else_value (ifn, orig_op->type,
     196            6 :                                                num_ops, orig_op->ops);
     197        11130 :   new_op->ops[num_ops + 1] = else_value;
     198        11130 :   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   1176387062 : do_valueize (tree op, tree (*valueize)(tree), bool &valueized)
     210              : {
     211   1176387062 :   if (valueize && TREE_CODE (op) == SSA_NAME)
     212              :     {
     213    743314367 :       tree tem = valueize (op);
     214    743314367 :       if (tem && tem != op)
     215              :         {
     216     51566829 :           op = tem;
     217     51566829 :           valueized = true;
     218              :         }
     219              :     }
     220   1176387062 :   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      2901542 : maybe_build_generic_op (gimple_match_op *res_op)
     228              : {
     229      2901542 :   tree_code code = (tree_code) res_op->code;
     230      2901542 :   tree val;
     231      2901542 :   switch (code)
     232              :     {
     233        10229 :     case REALPART_EXPR:
     234        10229 :     case IMAGPART_EXPR:
     235        10229 :     case VIEW_CONVERT_EXPR:
     236        10229 :       val = build1 (code, res_op->type, res_op->ops[0]);
     237        10229 :       res_op->set_value (val);
     238        10229 :       break;
     239        86970 :     case BIT_FIELD_REF:
     240        86970 :       val = build3 (code, res_op->type, res_op->ops[0], res_op->ops[1],
     241              :                     res_op->ops[2]);
     242        86970 :       REF_REVERSE_STORAGE_ORDER (val) = res_op->reverse;
     243        86970 :       res_op->set_value (val);
     244        86970 :       break;
     245      2901542 :     default:;
     246              :     }
     247      2901542 : }
     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         8295 : build_call_internal (internal_fn fn, gimple_match_op *res_op)
     254              : {
     255         8295 :   if (direct_internal_fn_p (fn))
     256              :     {
     257         8263 :       tree_pair types = direct_internal_fn_types (fn, res_op->type,
     258         8263 :                                                   res_op->ops);
     259         8263 :       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            2 :             case IFN_BSWAP:
     270            2 :             case IFN_BITREVERSE:
     271              :               /* For these 8 builtins large/huge _BitInt operand is ok
     272              :                  before bitint lowering pass.  */
     273            2 :               if (res_op->num_ops >= 1
     274            2 :                   && BITINT_TYPE_P (TREE_TYPE (res_op->ops[0]))
     275            2 :                   && (TYPE_PRECISION (TREE_TYPE (res_op->ops[0]))
     276            4 :                       > MAX_FIXED_MODE_SIZE)
     277            2 :                   && cfun
     278            4 :                   && (cfun->curr_properties & PROP_gimple_lbitint) == 0)
     279              :                 break;
     280           74 :               return NULL;
     281              : 
     282              :             default:
     283              :               return NULL;
     284              :             }
     285              :         }
     286              :     }
     287        33208 :   return gimple_build_call_internal (fn, res_op->num_ops,
     288              :                                      res_op->op_or_null (0),
     289              :                                      res_op->op_or_null (1),
     290              :                                      res_op->op_or_null (2),
     291              :                                      res_op->op_or_null (3),
     292              :                                      res_op->op_or_null (4),
     293              :                                      res_op->op_or_null (5),
     294         8221 :                                      res_op->op_or_null (6));
     295              : }
     296              : 
     297              : /* RES_OP is the result of a simplification.  If it is conditional,
     298              :    try to replace it with the equivalent UNCOND form, such as an
     299              :    IFN_COND_* call or a VEC_COND_EXPR.  Also try to resimplify the
     300              :    result of the replacement if appropriate, adding any new statements to
     301              :    SEQ and using VALUEIZE as the valueization function.  Return true if
     302              :    this resimplification occurred and resulted in at least one change.  */
     303              : 
     304              : static bool
     305    636668525 : maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
     306              :                                  tree (*valueize) (tree))
     307              : {
     308    636668525 :   if (!res_op->cond.cond)
     309              :     return false;
     310              : 
     311        15739 :   if (!res_op->cond.else_value
     312        15739 :       && res_op->code.is_tree_code ())
     313              :     {
     314              :       /* The "else" value doesn't matter.  If the "then" value is a
     315              :          gimple value, just use it unconditionally.  This isn't a
     316              :          simplification in itself, since there was no operation to
     317              :          build in the first place.  */
     318         1772 :       if (gimple_simplified_result_is_gimple_val (res_op))
     319              :         {
     320         1760 :           res_op->cond.cond = NULL_TREE;
     321         1760 :           return false;
     322              :         }
     323              : 
     324              :       /* Likewise if the operation would not trap.  */
     325           12 :       bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
     326           12 :                           && TYPE_OVERFLOW_TRAPS (res_op->type));
     327           12 :       tree_code op_code = (tree_code) res_op->code;
     328           12 :       bool op_could_trap;
     329              : 
     330              :       /* COND_EXPR will trap if, and only if, the condition
     331              :          traps and hence we have to check this.  For all other operations, we
     332              :          don't need to consider the operands.  */
     333           12 :       if (op_code == COND_EXPR)
     334            0 :         op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
     335              :       else
     336           24 :         op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
     337           12 :                                                 FLOAT_TYPE_P (res_op->type),
     338              :                                                 honor_trapv,
     339              :                                                 res_op->op_or_null (1));
     340              : 
     341           12 :       if (!op_could_trap)
     342              :         {
     343            6 :           res_op->cond.cond = NULL_TREE;
     344            6 :           return false;
     345              :         }
     346              :     }
     347              : 
     348              :   /* If the "then" value is a gimple value and the "else" value matters,
     349              :      create a (VEC_)COND_EXPR between them, then see if it can be further
     350              :      simplified.  */
     351        13973 :   gimple_match_op new_op;
     352        13973 :   if (res_op->cond.else_value
     353        13973 :       && gimple_simplified_result_is_gimple_val (res_op))
     354              :     {
     355         1253 :       if (VECTOR_TYPE_P (res_op->type))
     356              :         {
     357         1253 :           tree len = res_op->cond.len;
     358         1253 :           if (!len)
     359         1253 :             new_op.set_op (VEC_COND_EXPR, res_op->type,
     360              :                            res_op->cond.cond, res_op->ops[0],
     361              :                            res_op->cond.else_value);
     362              :           else
     363            0 :             new_op.set_op (IFN_VCOND_MASK_LEN, res_op->type,
     364              :                            res_op->cond.cond, res_op->ops[0],
     365              :                            res_op->cond.else_value,
     366              :                            res_op->cond.len, res_op->cond.bias);
     367              :         }
     368              :       else
     369            0 :         new_op.set_op (COND_EXPR, res_op->type,
     370              :                        res_op->cond.cond, res_op->ops[0],
     371              :                        res_op->cond.else_value);
     372         1253 :       *res_op = new_op;
     373         1253 :       return gimple_resimplify3 (seq, res_op, valueize);
     374              :     }
     375              : 
     376              :   /* Otherwise try rewriting the operation as an IFN_COND_* call.
     377              :      Again, this isn't a simplification in itself, since it's what
     378              :      RES_OP already described.  */
     379        12720 :   if (convert_conditional_op (res_op, &new_op))
     380        11130 :     *res_op = new_op;
     381              : 
     382              :   return false;
     383              : }
     384              : 
     385              : /* If RES_OP is a call to a conditional internal function, try simplifying
     386              :    the associated unconditional operation and using the result to build
     387              :    a new conditional operation.  For example, if RES_OP is:
     388              : 
     389              :      IFN_COND_ADD (COND, A, B, ELSE)
     390              : 
     391              :    try simplifying (plus A B) and using the result to build a replacement
     392              :    for the whole IFN_COND_ADD.
     393              : 
     394              :    Return true if this approach led to a simplification, otherwise leave
     395              :    RES_OP unchanged (and so suitable for other simplifications).  When
     396              :    returning true, add any new statements to SEQ and use VALUEIZE as the
     397              :    valueization function.
     398              : 
     399              :    RES_OP is known to be a call to IFN.  */
     400              : 
     401              : static bool
     402      3098227 : try_conditional_simplification (internal_fn ifn, gimple_match_op *res_op,
     403              :                                 gimple_seq *seq, tree (*valueize) (tree))
     404              : {
     405      3098227 :   code_helper op;
     406      3098227 :   tree_code code = conditional_internal_fn_code (ifn);
     407      3098227 :   int len_index = internal_fn_len_index (ifn);
     408      3098227 :   if (code != ERROR_MARK)
     409        12022 :     op = code;
     410              :   else
     411              :     {
     412      3086205 :       ifn = get_unconditional_internal_fn (ifn);
     413      3086205 :       if (ifn == IFN_LAST)
     414              :         return false;
     415         1150 :       op = as_combined_fn (ifn);
     416              :     }
     417              : 
     418        13172 :   unsigned int num_ops = res_op->num_ops;
     419              :   /* num_cond_ops = 2 for COND_ADD (MASK and ELSE)
     420              :      whereas num_cond_ops = 4 for COND_LEN_ADD (MASK, ELSE, LEN and BIAS).  */
     421        13172 :   unsigned int num_cond_ops = len_index < 0 ? 2 : 4;
     422        13172 :   tree else_value
     423        13172 :     = len_index < 0 ? res_op->ops[num_ops - 1] : res_op->ops[num_ops - 3];
     424        13172 :   tree len = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 2];
     425            0 :   tree bias = len_index < 0 ? NULL_TREE : res_op->ops[num_ops - 1];
     426        13172 :   gimple_match_op cond_op (gimple_match_cond (res_op->ops[0],
     427        13172 :                                               else_value, len, bias),
     428        13172 :                            op, res_op->type, num_ops - num_cond_ops);
     429              : 
     430        13172 :   memcpy (cond_op.ops, res_op->ops + 1, (num_ops - 1) * sizeof *cond_op.ops);
     431        13172 :   switch (num_ops - num_cond_ops)
     432              :     {
     433            0 :     case 1:
     434            0 :       if (!gimple_resimplify1 (seq, &cond_op, valueize))
     435              :         return false;
     436              :       break;
     437        12022 :     case 2:
     438        12022 :       if (!gimple_resimplify2 (seq, &cond_op, valueize))
     439              :         return false;
     440              :       break;
     441         1150 :     case 3:
     442         1150 :       if (!gimple_resimplify3 (seq, &cond_op, valueize))
     443              :         return false;
     444              :       break;
     445            0 :     default:
     446            0 :       gcc_unreachable ();
     447              :     }
     448         2947 :   *res_op = cond_op;
     449         2947 :   maybe_resimplify_conditional_op (seq, res_op, valueize);
     450         2947 :   return true;
     451              : }
     452              : 
     453              : /* Helper for the autogenerated code, valueize OP.  */
     454              : 
     455              : tree
     456    725084821 : do_valueize (tree (*valueize)(tree), tree op)
     457              : {
     458    725084821 :   if (valueize && TREE_CODE (op) == SSA_NAME)
     459              :     {
     460    539076687 :       tree tem = valueize (op);
     461    539076687 :       if (tem)
     462              :         return tem;
     463              :     }
     464              :   return op;
     465              : }
     466              : 
     467              : /* Push the exploded expression described by RES_OP as a statement to
     468              :    SEQ if necessary and return a gimple value denoting the value of the
     469              :    expression.  If RES is not NULL then the result will be always RES
     470              :    and even gimple values are pushed to SEQ.  */
     471              : 
     472              : tree
     473     12833207 : maybe_push_res_to_seq (gimple_match_op *res_op, gimple_seq *seq, tree res)
     474              : {
     475     12833207 :   tree *ops = res_op->ops;
     476     12833207 :   unsigned num_ops = res_op->num_ops;
     477              : 
     478              :   /* The caller should have converted conditional operations into an UNCOND
     479              :      form and resimplified as appropriate.  The conditional form only
     480              :      survives this far if that conversion failed.  */
     481     12833207 :   if (res_op->cond.cond)
     482              :     return NULL_TREE;
     483              : 
     484     12832808 :   if (res_op->code.is_tree_code ())
     485              :     {
     486     12817011 :       if (!res
     487     12817011 :           && gimple_simplified_result_is_gimple_val (res_op))
     488      7007786 :         return ops[0];
     489      5809225 :       if (mprts_hook)
     490              :         {
     491      2138697 :           tree tem = mprts_hook (res_op);
     492      2138697 :           if (tem)
     493              :             return tem;
     494              :         }
     495              :     }
     496              : 
     497      5770331 :   if (!seq)
     498              :     return NULL_TREE;
     499              : 
     500              :   /* Play safe and do not allow abnormals to be mentioned in
     501              :      newly created statements.  */
     502      2142139 :   for (unsigned int i = 0; i < num_ops; ++i)
     503      1364649 :     if (TREE_CODE (ops[i]) == SSA_NAME
     504      1364649 :         && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (ops[i]))
     505              :       return NULL_TREE;
     506              : 
     507       777490 :   if (res_op->code.is_tree_code ())
     508              :     {
     509       764462 :       auto code = tree_code (res_op->code);
     510       764462 :       if (!res)
     511              :         {
     512       683766 :           if (gimple_in_ssa_p (cfun))
     513       682797 :             res = make_ssa_name (res_op->type);
     514              :           else
     515          969 :             res = create_tmp_reg (res_op->type);
     516              :         }
     517       764462 :       maybe_build_generic_op (res_op);
     518      1953857 :       gimple *new_stmt = gimple_build_assign (res, code,
     519              :                                               res_op->op_or_null (0),
     520              :                                               res_op->op_or_null (1),
     521              :                                               res_op->op_or_null (2));
     522       764462 :       gimple_seq_add_stmt_without_update (seq, new_stmt);
     523       764462 :       return res;
     524              :     }
     525              :   else
     526              :     {
     527        13028 :       gcc_assert (num_ops != 0);
     528        13028 :       auto fn = combined_fn (res_op->code);
     529        13028 :       gcall *new_stmt = NULL;
     530        13028 :       if (internal_fn_p (fn))
     531              :         {
     532              :           /* Generate the given function if we can.  */
     533         8295 :           internal_fn ifn = as_internal_fn (fn);
     534              : 
     535              :           /* We can't and should not emit calls to non-const functions.  */
     536         8295 :           if (!(internal_fn_flags (ifn) & ECF_CONST))
     537              :             return NULL_TREE;
     538              : 
     539         8295 :           new_stmt = build_call_internal (ifn, res_op);
     540         8295 :           if (!new_stmt)
     541              :             return NULL_TREE;
     542              :         }
     543              :       else
     544              :         {
     545              :           /* Find the function we want to call.  */
     546         4733 :           tree decl = builtin_decl_implicit (as_builtin_fn (fn));
     547         4733 :           if (!decl)
     548              :             return NULL;
     549              : 
     550              :           /* We can't and should not emit calls to non-const functions.  */
     551         4727 :           if (!(flags_from_decl_or_type (decl) & ECF_CONST))
     552              :             return NULL;
     553              : 
     554         8108 :           new_stmt = gimple_build_call (decl, num_ops,
     555              :                                         res_op->op_or_null (0),
     556              :                                         res_op->op_or_null (1),
     557              :                                         res_op->op_or_null (2),
     558              :                                         res_op->op_or_null (3),
     559              :                                         res_op->op_or_null (4));
     560              :         }
     561        12187 :       if (!res)
     562              :         {
     563         1255 :           if (gimple_in_ssa_p (cfun))
     564         1255 :             res = make_ssa_name (res_op->type);
     565              :           else
     566            0 :             res = create_tmp_reg (res_op->type);
     567              :         }
     568        12187 :       gimple_call_set_lhs (new_stmt, res);
     569        12187 :       gimple_seq_add_stmt_without_update (seq, new_stmt);
     570        12187 :       return res;
     571              :     }
     572              : }
     573              : 
     574              : 
     575              : /* Public API overloads follow for operation being tree_code or
     576              :    built_in_function and for one to three operands or arguments.
     577              :    They return NULL_TREE if nothing could be simplified or
     578              :    the resulting simplified value with parts pushed to SEQ.
     579              :    If SEQ is NULL then if the simplification needs to create
     580              :    new stmts it will fail.  If VALUEIZE is non-NULL then all
     581              :    SSA names will be valueized using that hook prior to
     582              :    applying simplifications.  */
     583              : 
     584              : /* Unary ops.  */
     585              : 
     586              : tree
     587       338645 : gimple_simplify (enum tree_code code, tree type,
     588              :                  tree op0,
     589              :                  gimple_seq *seq, tree (*valueize)(tree))
     590              : {
     591       338645 :   if (constant_for_folding (op0))
     592              :     {
     593        29410 :       tree res = const_unop (code, type, op0);
     594        29410 :       if (res != NULL_TREE
     595        29162 :           && CONSTANT_CLASS_P (res))
     596              :         return res;
     597              :     }
     598              : 
     599       309483 :   gimple_match_op res_op;
     600       309483 :   if (!gimple_simplify (&res_op, seq, valueize, code, type, op0))
     601              :     return NULL_TREE;
     602        11115 :   return maybe_push_res_to_seq (&res_op, seq);
     603              : }
     604              : 
     605              : /* Binary ops.  */
     606              : 
     607              : tree
     608     25128725 : gimple_simplify (enum tree_code code, tree type,
     609              :                  tree op0, tree op1,
     610              :                  gimple_seq *seq, tree (*valueize)(tree))
     611              : {
     612     25128725 :   if (constant_for_folding (op0) && constant_for_folding (op1))
     613              :     {
     614      1761994 :       tree res = const_binop (code, type, op0, op1);
     615      1761994 :       if (res != NULL_TREE
     616      1760400 :           && CONSTANT_CLASS_P (res))
     617              :         return res;
     618              :     }
     619              : 
     620              :   /* Canonicalize operand order both for matching and fallback stmt
     621              :      generation.  */
     622     23368325 :   if ((commutative_tree_code (code)
     623      6694009 :        || TREE_CODE_CLASS (code) == tcc_comparison)
     624     29938977 :       && tree_swap_operands_p (op0, op1))
     625              :     {
     626        42564 :       std::swap (op0, op1);
     627        42564 :       if (TREE_CODE_CLASS (code) == tcc_comparison)
     628         3838 :         code = swap_tree_comparison (code);
     629              :     }
     630              : 
     631     23368325 :   gimple_match_op res_op;
     632     23368325 :   if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1))
     633              :     return NULL_TREE;
     634      2535970 :   return maybe_push_res_to_seq (&res_op, seq);
     635              : }
     636              : 
     637              : /* Ternary ops.  */
     638              : 
     639              : tree
     640        44818 : gimple_simplify (enum tree_code code, tree type,
     641              :                  tree op0, tree op1, tree op2,
     642              :                  gimple_seq *seq, tree (*valueize)(tree))
     643              : {
     644        46105 :   if (constant_for_folding (op0) && constant_for_folding (op1)
     645        46105 :       && constant_for_folding (op2))
     646              :     {
     647         1287 :       tree res = fold_ternary/*_to_constant */ (code, type, op0, op1, op2);
     648         1287 :       if (res != NULL_TREE
     649         1287 :           && CONSTANT_CLASS_P (res))
     650              :         return res;
     651              :     }
     652              : 
     653              :   /* Canonicalize operand order both for matching and fallback stmt
     654              :      generation.  */
     655        43531 :   if (commutative_ternary_tree_code (code)
     656        43531 :       && tree_swap_operands_p (op0, op1))
     657              :     std::swap (op0, op1);
     658              : 
     659        43531 :   gimple_match_op res_op;
     660        43531 :   if (!gimple_simplify (&res_op, seq, valueize, code, type, op0, op1, op2))
     661              :     return NULL_TREE;
     662        11841 :   return maybe_push_res_to_seq (&res_op, seq);
     663              : }
     664              : 
     665              : /* Builtin or internal function with one argument.  */
     666              : 
     667              : tree
     668        24604 : gimple_simplify (combined_fn fn, tree type,
     669              :                  tree arg0,
     670              :                  gimple_seq *seq, tree (*valueize)(tree))
     671              : {
     672        24604 :   if (constant_for_folding (arg0))
     673              :     {
     674            0 :       tree res = fold_const_call (fn, type, arg0);
     675            0 :       if (res && CONSTANT_CLASS_P (res))
     676              :         return res;
     677              :     }
     678              : 
     679        24604 :   gimple_match_op res_op;
     680        24604 :   if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0))
     681              :     return NULL_TREE;
     682            0 :   return maybe_push_res_to_seq (&res_op, seq);
     683              : }
     684              : 
     685              : /* Builtin or internal function with two arguments.  */
     686              : 
     687              : tree
     688            0 : gimple_simplify (combined_fn fn, tree type,
     689              :                  tree arg0, tree arg1,
     690              :                  gimple_seq *seq, tree (*valueize)(tree))
     691              : {
     692            0 :   if (constant_for_folding (arg0)
     693            0 :       && constant_for_folding (arg1))
     694              :     {
     695            0 :       tree res = fold_const_call (fn, type, arg0, arg1);
     696            0 :       if (res && CONSTANT_CLASS_P (res))
     697              :         return res;
     698              :     }
     699              : 
     700            0 :   gimple_match_op res_op;
     701            0 :   if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1))
     702              :     return NULL_TREE;
     703            0 :   return maybe_push_res_to_seq (&res_op, seq);
     704              : }
     705              : 
     706              : /* Builtin or internal function with three arguments.  */
     707              : 
     708              : tree
     709            0 : gimple_simplify (combined_fn fn, tree type,
     710              :                  tree arg0, tree arg1, tree arg2,
     711              :                  gimple_seq *seq, tree (*valueize)(tree))
     712              : {
     713            0 :   if (constant_for_folding (arg0)
     714            0 :       && constant_for_folding (arg1)
     715            0 :       && constant_for_folding (arg2))
     716              :     {
     717            0 :       tree res = fold_const_call (fn, type, arg0, arg1, arg2);
     718            0 :       if (res && CONSTANT_CLASS_P (res))
     719              :         return res;
     720              :     }
     721              : 
     722            0 :   gimple_match_op res_op;
     723            0 :   if (!gimple_simplify (&res_op, seq, valueize, fn, type, arg0, arg1, arg2))
     724              :     return NULL_TREE;
     725            0 :   return maybe_push_res_to_seq (&res_op, seq);
     726              : }
     727              : 
     728              : /* Common subroutine of gimple_extract_op and gimple_simplify.  Try to
     729              :    describe STMT in RES_OP, returning true on success.  Before recording
     730              :    an operand, call:
     731              : 
     732              :    - VALUEIZE_OP for all top-level operand
     733              : 
     734              :    This routine takes a tree argument and returns a tree.  */
     735              : 
     736              : template<typename ValueizeOp>
     737              : inline bool
     738   1319386891 : gimple_extract (gimple *stmt, gimple_match_op *res_op,
     739              :                 ValueizeOp valueize_op)
     740              : {
     741   1319386891 :   switch (gimple_code (stmt))
     742              :     {
     743    610367683 :     case GIMPLE_ASSIGN:
     744              :       {
     745    610367683 :         enum tree_code code = gimple_assign_rhs_code (stmt);
     746    610367683 :         tree type = TREE_TYPE (gimple_assign_lhs (stmt));
     747    610367683 :         switch (gimple_assign_rhs_class (stmt))
     748              :           {
     749    281406368 :           case GIMPLE_SINGLE_RHS:
     750    281406368 :             if (code == REALPART_EXPR
     751              :                 || code == IMAGPART_EXPR
     752    281406368 :                 || code == VIEW_CONVERT_EXPR)
     753              :               {
     754      7857657 :                 tree op0 = TREE_OPERAND (gimple_assign_rhs1 (stmt), 0);
     755              :                 /* op0 needs to be a SSA name or an min invariant. */
     756      7857657 :                 if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
     757              :                   return false;
     758      5656528 :                 res_op->set_op (code, type, valueize_op (op0));
     759      5656528 :                 return true;
     760              :               }
     761    273548711 :             else if (code == BIT_FIELD_REF)
     762              :               {
     763      1752622 :                 tree rhs1 = gimple_assign_rhs1 (stmt);
     764      1752622 :                 tree op0 = valueize_op (TREE_OPERAND (rhs1, 0));
     765              :                 /* op0 needs to be a SSA name or an min invariant. */
     766      1752622 :                 if (TREE_CODE (op0) != SSA_NAME && !is_gimple_min_invariant (op0))
     767              :                   return false;
     768      1139521 :                 res_op->set_op (code, type, op0,
     769      1139521 :                                 TREE_OPERAND (rhs1, 1),
     770      1139521 :                                 TREE_OPERAND (rhs1, 2),
     771      1139521 :                                 REF_REVERSE_STORAGE_ORDER (rhs1));
     772      1139521 :                 return true;
     773              :               }
     774    271796089 :             else if (code == SSA_NAME)
     775              :               {
     776     44735169 :                 tree op0 = gimple_assign_rhs1 (stmt);
     777     44735169 :                 res_op->set_op (TREE_CODE (op0), type, valueize_op (op0));
     778     44735169 :                 return true;
     779              :               }
     780              :             break;
     781     83385393 :           case GIMPLE_UNARY_RHS:
     782              :             {
     783     83385393 :               tree rhs1 = gimple_assign_rhs1 (stmt);
     784     83385393 :               res_op->set_op (code, type, valueize_op (rhs1));
     785     83385393 :               return true;
     786              :             }
     787    244257792 :           case GIMPLE_BINARY_RHS:
     788              :             {
     789    244257792 :               tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
     790    244257792 :               tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
     791    244257792 :               res_op->set_op (code, type, rhs1, rhs2);
     792    244257792 :               return true;
     793              :             }
     794      1318130 :           case GIMPLE_TERNARY_RHS:
     795              :             {
     796      1318130 :               tree rhs1 = valueize_op (gimple_assign_rhs1 (stmt));
     797      1318130 :               tree rhs2 = valueize_op (gimple_assign_rhs2 (stmt));
     798      1318130 :               tree rhs3 = valueize_op (gimple_assign_rhs3 (stmt));
     799      1318130 :               res_op->set_op (code, type, rhs1, rhs2, rhs3);
     800      1318130 :               return true;
     801              :             }
     802            0 :           default:
     803            0 :             gcc_unreachable ();
     804              :           }
     805              :         break;
     806              :       }
     807              : 
     808     70071691 :     case GIMPLE_CALL:
     809              :       /* ???  This way we can't simplify calls with side-effects.  */
     810     70071691 :       if (gimple_call_lhs (stmt) != NULL_TREE
     811     36915662 :           && gimple_call_num_args (stmt) >= 1
     812    104969535 :           && gimple_call_num_args (stmt) <= 7)
     813              :         {
     814              :           combined_fn cfn;
     815     34812215 :           if (gimple_call_internal_p (stmt))
     816      3156169 :             cfn = as_combined_fn (gimple_call_internal_fn (stmt));
     817              :           else
     818              :             {
     819     31656046 :               tree fn = gimple_call_fn (stmt);
     820     31656046 :               if (!fn)
     821              :                 return false;
     822              : 
     823     31656046 :               fn = valueize_op (fn);
     824     31656046 :               if (TREE_CODE (fn) != ADDR_EXPR
     825     31656046 :                   || TREE_CODE (TREE_OPERAND (fn, 0)) != FUNCTION_DECL)
     826              :                 return false;
     827              : 
     828     30166578 :               tree decl = TREE_OPERAND (fn, 0);
     829     30166578 :               if (DECL_BUILT_IN_CLASS (decl) != BUILT_IN_NORMAL
     830     30166578 :                   || !gimple_builtin_call_types_compatible_p (stmt, decl))
     831     19855805 :                 return false;
     832              : 
     833     10310773 :               cfn = as_combined_fn (DECL_FUNCTION_CODE (decl));
     834              :             }
     835              : 
     836     13466942 :           unsigned int num_args = gimple_call_num_args (stmt);
     837     13466942 :           res_op->set_op (cfn, TREE_TYPE (gimple_call_lhs (stmt)), num_args);
     838     44597993 :           for (unsigned i = 0; i < num_args; ++i)
     839     62003994 :             res_op->ops[i] = valueize_op (gimple_call_arg (stmt, i));
     840              :           return true;
     841              :         }
     842              :       break;
     843              : 
     844    244276646 :     case GIMPLE_COND:
     845              :       {
     846    244276646 :         tree lhs = valueize_op (gimple_cond_lhs (stmt));
     847    244276646 :         tree rhs = valueize_op (gimple_cond_rhs (stmt));
     848    244276646 :         res_op->set_op (gimple_cond_code (stmt), boolean_type_node, lhs, rhs);
     849    244276646 :         return true;
     850              :       }
     851              : 
     852              :     default:
     853              :       break;
     854              :     }
     855              : 
     856              :   return false;
     857              : }
     858              : 
     859              : /* Try to describe STMT in RES_OP, returning true on success.
     860              :    For GIMPLE_CONDs, describe the condition that is being tested.
     861              :    For GIMPLE_ASSIGNs, describe the rhs of the assignment.
     862              :    For GIMPLE_CALLs, describe the call.  */
     863              : 
     864              : bool
     865      2156305 : gimple_extract_op (gimple *stmt, gimple_match_op *res_op)
     866              : {
     867      2156305 :   auto nop = [](tree op) { return op; };
     868      2156305 :   return gimple_extract (stmt, res_op, nop);
     869              : }
     870              : 
     871              : /* The main STMT based simplification entry.  It is used by the fold_stmt
     872              :    and the fold_stmt_to_constant APIs.  */
     873              : 
     874              : bool
     875   1317230586 : gimple_simplify (gimple *stmt, gimple_match_op *res_op, gimple_seq *seq,
     876              :                  tree (*valueize)(tree), tree (*top_valueize)(tree))
     877              : {
     878   1317230586 :   bool valueized = false;
     879   2493617648 :   auto valueize_op = [&](tree op)
     880              :     {
     881   1176387062 :       return do_valueize (op, top_valueize, valueized);
     882   1317230586 :     };
     883              : 
     884   1317230586 :   if (!gimple_extract (stmt, res_op, valueize_op))
     885              :     return false;
     886              : 
     887    636794629 :   if (res_op->code.is_internal_fn ())
     888              :     {
     889      3098227 :       internal_fn ifn = internal_fn (res_op->code);
     890      3098227 :       if (try_conditional_simplification (ifn, res_op, seq, valueize))
     891              :         return true;
     892              :     }
     893              : 
     894    636791682 :   if (!res_op->reverse
     895    636791682 :       && res_op->num_ops
     896   1273583364 :       && res_op->resimplify (seq, valueize))
     897              :     return true;
     898              : 
     899    570224873 :   return valueized;
     900              : }
     901              : 
     902              : /* Helper that matches and simplifies the toplevel result from
     903              :    a gimple_simplify run (where we don't want to build
     904              :    a stmt in case it's used in in-place folding).  Replaces
     905              :    RES_OP with a simplified and/or canonicalized result and
     906              :    returns whether any change was made.  */
     907              : 
     908              : static bool
     909    153910495 : gimple_resimplify1 (gimple_seq *seq, gimple_match_op *res_op,
     910              :                     tree (*valueize)(tree))
     911              : {
     912    153910495 :   if (constant_for_folding (res_op->ops[0]))
     913              :     {
     914     13451367 :       tree tem = NULL_TREE;
     915     13451367 :       if (res_op->code.is_tree_code ())
     916              :         {
     917     12246984 :           auto code = tree_code (res_op->code);
     918     12246984 :           if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
     919     11441278 :               && TREE_CODE_LENGTH (code) == 1)
     920     11441278 :             tem = const_unop (code, res_op->type, res_op->ops[0]);
     921              :         }
     922              :       else
     923      1204383 :         tem = fold_const_call (combined_fn (res_op->code), res_op->type,
     924              :                                res_op->ops[0]);
     925     12645661 :       if (tem != NULL_TREE
     926     11374603 :           && CONSTANT_CLASS_P (tem))
     927              :         {
     928     11374603 :           if (TREE_OVERFLOW_P (tem))
     929         2753 :             tem = drop_tree_overflow (tem);
     930     11374603 :           res_op->set_value (tem);
     931     11374603 :           maybe_resimplify_conditional_op (seq, res_op, valueize);
     932     11374603 :           return true;
     933              :         }
     934              :     }
     935              : 
     936              :   /* Limit recursion, there are cases like PR80887 and others, for
     937              :      example when value-numbering presents us with unfolded expressions
     938              :      that we are really not prepared to handle without eventual
     939              :      oscillation like ((_50 + 0) + 8) where _50 gets mapped to _50
     940              :      itself as available expression.  */
     941    142535892 :   static unsigned depth;
     942    142535892 :   if (depth > 10)
     943              :     {
     944            2 :       if (dump_file && (dump_flags & TDF_FOLDING))
     945            0 :         fprintf (dump_file, "Aborting expression simplification due to "
     946              :                  "deep recursion\n");
     947            2 :       return false;
     948              :     }
     949              : 
     950    142535890 :   ++depth;
     951    142535890 :   gimple_match_op res_op2 (*res_op);
     952    142535890 :   if (gimple_simplify (&res_op2, seq, valueize,
     953              :                        res_op->code, res_op->type, res_op->ops[0]))
     954              :     {
     955      2622160 :       --depth;
     956      2622160 :       *res_op = res_op2;
     957      2622160 :       return true;
     958              :     }
     959    139913730 :   --depth;
     960              : 
     961    139913730 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
     962              :     return true;
     963              : 
     964              :   return false;
     965              : }
     966              : 
     967              : /* Helper that matches and simplifies the toplevel result from
     968              :    a gimple_simplify run (where we don't want to build
     969              :    a stmt in case it's used in in-place folding).  Replaces
     970              :    RES_OP with a simplified and/or canonicalized result and
     971              :    returns whether any change was made.  */
     972              : 
     973              : static bool
     974    516325396 : gimple_resimplify2 (gimple_seq *seq, gimple_match_op *res_op,
     975              :                     tree (*valueize)(tree))
     976              : {
     977    516325396 :   if (constant_for_folding (res_op->ops[0])
     978    516325396 :       && constant_for_folding (res_op->ops[1]))
     979              :     {
     980     22777010 :       tree tem = NULL_TREE;
     981     22777010 :       if (res_op->code.is_tree_code ())
     982              :         {
     983     22645384 :           auto code = tree_code (res_op->code);
     984     22645384 :           if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
     985     22645384 :               && TREE_CODE_LENGTH (code) == 2)
     986     22645384 :             tem = const_binop (code, res_op->type,
     987              :                                res_op->ops[0], res_op->ops[1]);
     988              :         }
     989              :       else
     990       131626 :         tem = fold_const_call (combined_fn (res_op->code), res_op->type,
     991              :                                res_op->ops[0], res_op->ops[1]);
     992     22777010 :       if (tem != NULL_TREE
     993     22601260 :           && CONSTANT_CLASS_P (tem))
     994              :         {
     995     22601214 :           if (TREE_OVERFLOW_P (tem))
     996          671 :             tem = drop_tree_overflow (tem);
     997     22601214 :           res_op->set_value (tem);
     998     22601214 :           maybe_resimplify_conditional_op (seq, res_op, valueize);
     999     22601214 :           return true;
    1000              :         }
    1001              :     }
    1002              : 
    1003              :   /* Canonicalize operand order.  */
    1004    493724182 :   bool canonicalized = false;
    1005    493724182 :   bool is_comparison
    1006    493724182 :     = (res_op->code.is_tree_code ()
    1007    493724182 :        && TREE_CODE_CLASS (tree_code (res_op->code)) == tcc_comparison);
    1008    236714618 :   if ((is_comparison || commutative_binary_op_p (res_op->code, res_op->type))
    1009    427380666 :       && tree_swap_operands_p (res_op->ops[0], res_op->ops[1]))
    1010              :     {
    1011      8338341 :       std::swap (res_op->ops[0], res_op->ops[1]);
    1012      8338341 :       if (is_comparison)
    1013      3356738 :         res_op->code = swap_tree_comparison (tree_code (res_op->code));
    1014              :       canonicalized = true;
    1015              :     }
    1016              : 
    1017              :   /* Limit recursion, see gimple_resimplify1.  */
    1018    493724182 :   static unsigned depth;
    1019    493724182 :   if (depth > 10)
    1020              :     {
    1021        43699 :       if (dump_file && (dump_flags & TDF_FOLDING))
    1022            0 :         fprintf (dump_file, "Aborting expression simplification due to "
    1023              :                  "deep recursion\n");
    1024        43699 :       return false;
    1025              :     }
    1026              : 
    1027    493680483 :   ++depth;
    1028    493680483 :   gimple_match_op res_op2 (*res_op);
    1029    493680483 :   if (gimple_simplify (&res_op2, seq, valueize,
    1030              :                        res_op->code, res_op->type,
    1031              :                        res_op->ops[0], res_op->ops[1]))
    1032              :     {
    1033     38716250 :       --depth;
    1034     38716250 :       *res_op = res_op2;
    1035     38716250 :       return true;
    1036              :     }
    1037    454964233 :   --depth;
    1038              : 
    1039    454964233 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
    1040              :     return true;
    1041              : 
    1042              :   return canonicalized;
    1043              : }
    1044              : 
    1045              : /* Helper that matches and simplifies the toplevel result from
    1046              :    a gimple_simplify run (where we don't want to build
    1047              :    a stmt in case it's used in in-place folding).  Replaces
    1048              :    RES_OP with a simplified and/or canonicalized result and
    1049              :    returns whether any change was made.  */
    1050              : 
    1051              : static bool
    1052      7286780 : gimple_resimplify3 (gimple_seq *seq, gimple_match_op *res_op,
    1053              :                     tree (*valueize)(tree))
    1054              : {
    1055      7286780 :   if (constant_for_folding (res_op->ops[0])
    1056       871484 :       && constant_for_folding (res_op->ops[1])
    1057      7949358 :       && constant_for_folding (res_op->ops[2]))
    1058              :     {
    1059        89403 :       tree tem = NULL_TREE;
    1060        89403 :       if (res_op->code.is_tree_code ())
    1061              :         {
    1062        51159 :           auto code = tree_code (res_op->code);
    1063        51159 :           if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (code))
    1064        51159 :               && TREE_CODE_LENGTH (code) == 3)
    1065        51159 :             tem = fold_ternary/*_to_constant*/ (code, res_op->type,
    1066              :                                                 res_op->ops[0], res_op->ops[1],
    1067              :                                                 res_op->ops[2]);
    1068              :         }
    1069              :       else
    1070        38244 :         tem = fold_const_call (combined_fn (res_op->code), res_op->type,
    1071              :                                res_op->ops[0], res_op->ops[1], res_op->ops[2]);
    1072        89403 :       if (tem != NULL_TREE
    1073        51139 :           && CONSTANT_CLASS_P (tem))
    1074              :         {
    1075        50971 :           if (TREE_OVERFLOW_P (tem))
    1076            4 :             tem = drop_tree_overflow (tem);
    1077        50971 :           res_op->set_value (tem);
    1078        50971 :           maybe_resimplify_conditional_op (seq, res_op, valueize);
    1079        50971 :           return true;
    1080              :         }
    1081              :     }
    1082              : 
    1083              :   /* Canonicalize operand order.  */
    1084      7235809 :   bool canonicalized = false;
    1085      7235809 :   int argno = first_commutative_argument (res_op->code, res_op->type);
    1086      7235809 :   if (argno >= 0
    1087      7235809 :       && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
    1088              :     {
    1089         1185 :       std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
    1090         1185 :       canonicalized = true;
    1091              :     }
    1092              : 
    1093              :   /* Limit recursion, see gimple_resimplify1.  */
    1094      7235809 :   static unsigned depth;
    1095      7235809 :   if (depth > 10)
    1096              :     {
    1097           33 :       if (dump_file && (dump_flags & TDF_FOLDING))
    1098            0 :         fprintf (dump_file, "Aborting expression simplification due to "
    1099              :                  "deep recursion\n");
    1100           33 :       return false;
    1101              :     }
    1102              : 
    1103      7235776 :   ++depth;
    1104      7235776 :   gimple_match_op res_op2 (*res_op);
    1105      7235776 :   if (gimple_simplify (&res_op2, seq, valueize,
    1106              :                        res_op->code, res_op->type,
    1107              :                        res_op->ops[0], res_op->ops[1], res_op->ops[2]))
    1108              :     {
    1109       434159 :       --depth;
    1110       434159 :       *res_op = res_op2;
    1111       434159 :       return true;
    1112              :     }
    1113      6801617 :   --depth;
    1114              : 
    1115      6801617 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
    1116              :     return true;
    1117              : 
    1118              :   return canonicalized;
    1119              : }
    1120              : 
    1121              : /* Helper that matches and simplifies the toplevel result from
    1122              :    a gimple_simplify run (where we don't want to build
    1123              :    a stmt in case it's used in in-place folding).  Replaces
    1124              :    RES_OP with a simplified and/or canonicalized result and
    1125              :    returns whether any change was made.  */
    1126              : 
    1127              : static bool
    1128       246321 : gimple_resimplify4 (gimple_seq *seq, gimple_match_op *res_op,
    1129              :                     tree (*valueize)(tree))
    1130              : {
    1131              :   /* No constant folding is defined for four-operand functions.  */
    1132              : 
    1133              :   /* Canonicalize operand order.  */
    1134       246321 :   bool canonicalized = false;
    1135       246321 :   int argno = first_commutative_argument (res_op->code, res_op->type);
    1136       246321 :   if (argno >= 0
    1137       246321 :       && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
    1138              :     {
    1139            0 :       std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
    1140            0 :       canonicalized = true;
    1141              :     }
    1142              : 
    1143              :   /* Limit recursion, see gimple_resimplify1.  */
    1144       246321 :   static unsigned depth;
    1145       246321 :   if (depth > 10)
    1146              :     {
    1147            0 :       if (dump_file && (dump_flags & TDF_FOLDING))
    1148            0 :         fprintf (dump_file, "Aborting expression simplification due to "
    1149              :                  "deep recursion\n");
    1150            0 :       return false;
    1151              :     }
    1152              : 
    1153       246321 :   ++depth;
    1154       246321 :   gimple_match_op res_op2 (*res_op);
    1155       246321 :   if (gimple_simplify (&res_op2, seq, valueize,
    1156              :                        res_op->code, res_op->type,
    1157              :                        res_op->ops[0], res_op->ops[1], res_op->ops[2],
    1158              :                        res_op->ops[3]))
    1159              :     {
    1160            0 :       --depth;
    1161            0 :       *res_op = res_op2;
    1162            0 :       return true;
    1163              :     }
    1164       246321 :   --depth;
    1165              : 
    1166       246321 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
    1167              :     return true;
    1168              : 
    1169              :   return canonicalized;
    1170              : }
    1171              : 
    1172              : /* Helper that matches and simplifies the toplevel result from
    1173              :    a gimple_simplify run (where we don't want to build
    1174              :    a stmt in case it's used in in-place folding).  Replaces
    1175              :    RES_OP with a simplified and/or canonicalized result and
    1176              :    returns whether any change was made.  */
    1177              : 
    1178              : static bool
    1179        24815 : gimple_resimplify5 (gimple_seq *seq, gimple_match_op *res_op,
    1180              :                     tree (*valueize)(tree))
    1181              : {
    1182              :   /* No constant folding is defined for five-operand functions.  */
    1183              : 
    1184              :   /* Canonicalize operand order.  */
    1185        24815 :   bool canonicalized = false;
    1186        24815 :   int argno = first_commutative_argument (res_op->code, res_op->type);
    1187        24815 :   if (argno >= 0
    1188        24815 :       && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
    1189              :     {
    1190            0 :       std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
    1191            0 :       canonicalized = true;
    1192              :     }
    1193              : 
    1194        24815 :   gimple_match_op res_op2 (*res_op);
    1195        24815 :   if (gimple_simplify (&res_op2, seq, valueize,
    1196              :                        res_op->code, res_op->type,
    1197              :                        res_op->ops[0], res_op->ops[1], res_op->ops[2],
    1198              :                        res_op->ops[3], res_op->ops[4]))
    1199              :     {
    1200            0 :       *res_op = res_op2;
    1201            0 :       return true;
    1202              :     }
    1203              : 
    1204        24815 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
    1205              :     return true;
    1206              : 
    1207              :   return canonicalized;
    1208              : }
    1209              : 
    1210              : /* Helper that matches and simplifies the toplevel result from
    1211              :    a gimple_simplify run (where we don't want to build
    1212              :    a stmt in case it's used in in-place folding).  Replaces
    1213              :    RES_OP with a simplified and/or canonicalized result and
    1214              :    returns whether any change was made.  */
    1215              : 
    1216              : static bool
    1217       604003 : gimple_resimplify6 (gimple_seq *seq, gimple_match_op *res_op,
    1218              :                     tree (*valueize)(tree))
    1219              : {
    1220              :   /* No constant folding is defined for six-operand functions.  */
    1221              : 
    1222              :   /* Canonicalize operand order.  */
    1223       604003 :   bool canonicalized = false;
    1224       604003 :   int argno = first_commutative_argument (res_op->code, res_op->type);
    1225       604003 :   if (argno >= 0
    1226       604003 :       && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
    1227              :     {
    1228            0 :       std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
    1229            0 :       canonicalized = true;
    1230              :     }
    1231              : 
    1232       604003 :   gimple_match_op res_op2 (*res_op);
    1233       604003 :   if (gimple_simplify (&res_op2, seq, valueize,
    1234              :                        res_op->code, res_op->type,
    1235              :                        res_op->ops[0], res_op->ops[1], res_op->ops[2],
    1236              :                        res_op->ops[3], res_op->ops[4], res_op->ops[5]))
    1237              :     {
    1238            0 :       *res_op = res_op2;
    1239            0 :       return true;
    1240              :     }
    1241              : 
    1242       604003 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
    1243              :     return true;
    1244              : 
    1245              :   return canonicalized;
    1246              : }
    1247              : 
    1248              : /* Helper that matches and simplifies the toplevel result from
    1249              :    a gimple_simplify run (where we don't want to build
    1250              :    a stmt in case it's used in in-place folding).  Replaces
    1251              :    RES_OP with a simplified and/or canonicalized result and
    1252              :    returns whether any change was made.  */
    1253              : 
    1254              : static bool
    1255        84071 : gimple_resimplify7 (gimple_seq *seq, gimple_match_op *res_op,
    1256              :                     tree (*valueize)(tree))
    1257              : {
    1258              :   /* No constant folding is defined for seven-operand functions.  */
    1259              : 
    1260              :   /* Canonicalize operand order.  */
    1261        84071 :   bool canonicalized = false;
    1262        84071 :   int argno = first_commutative_argument (res_op->code, res_op->type);
    1263        84071 :   if (argno >= 0
    1264        84071 :       && tree_swap_operands_p (res_op->ops[argno], res_op->ops[argno + 1]))
    1265              :     {
    1266            0 :       std::swap (res_op->ops[argno], res_op->ops[argno + 1]);
    1267            0 :       canonicalized = true;
    1268              :     }
    1269              : 
    1270        84071 :   gimple_match_op res_op2 (*res_op);
    1271        84071 :   if (gimple_simplify (&res_op2, seq, valueize,
    1272              :                        res_op->code, res_op->type,
    1273              :                        res_op->ops[0], res_op->ops[1], res_op->ops[2],
    1274              :                        res_op->ops[3], res_op->ops[4], res_op->ops[5],
    1275              :                        res_op->ops[6]))
    1276              :     {
    1277            0 :       *res_op = res_op2;
    1278            0 :       return true;
    1279              :     }
    1280              : 
    1281        84071 :   if (maybe_resimplify_conditional_op (seq, res_op, valueize))
    1282              :     return true;
    1283              : 
    1284              :   return canonicalized;
    1285              : }
    1286              : 
    1287              : /* Return a canonical form for CODE when operating on TYPE.  The idea
    1288              :    is to remove redundant ways of representing the same operation so
    1289              :    that code_helpers can be hashed and compared for equality.
    1290              : 
    1291              :    The only current canonicalization is to replace built-in functions
    1292              :    with internal functions, in cases where internal-fn.def defines
    1293              :    such an internal function.
    1294              : 
    1295              :    Note that the new code_helper cannot necessarily be used in place of
    1296              :    the original code_helper.  For example, the new code_helper might be
    1297              :    an internal function that the target does not support.  */
    1298              : 
    1299              : code_helper
    1300       124927 : canonicalize_code (code_helper code, tree type)
    1301              : {
    1302       124927 :   if (code.is_fn_code ())
    1303         6713 :     return associated_internal_fn (combined_fn (code), type);
    1304       118214 :   return code;
    1305              : }
    1306              : 
    1307              : /* Return true if CODE is a binary operation and if CODE is commutative when
    1308              :    operating on type TYPE.  */
    1309              : 
    1310              : bool
    1311    236782114 : commutative_binary_op_p (code_helper code, tree type)
    1312              : {
    1313    236782114 :   if (code.is_tree_code ())
    1314    230825115 :     return commutative_tree_code (tree_code (code));
    1315      5956999 :   auto cfn = combined_fn (code);
    1316      5956999 :   return commutative_binary_fn_p (associated_internal_fn (cfn, type));
    1317              : }
    1318              : 
    1319              : /* Return true if CODE represents a ternary operation and if the first two
    1320              :    operands are commutative when CODE is operating on TYPE.  */
    1321              : 
    1322              : bool
    1323            0 : commutative_ternary_op_p (code_helper code, tree type)
    1324              : {
    1325            0 :   if (code.is_tree_code ())
    1326            0 :     return commutative_ternary_tree_code (tree_code (code));
    1327            0 :   auto cfn = combined_fn (code);
    1328            0 :   return commutative_ternary_fn_p (associated_internal_fn (cfn, type));
    1329              : }
    1330              : 
    1331              : /* If CODE is commutative in two consecutive operands, return the
    1332              :    index of the first, otherwise return -1.  */
    1333              : 
    1334              : int
    1335      8225764 : first_commutative_argument (code_helper code, tree type)
    1336              : {
    1337      8225764 :   if (code.is_tree_code ())
    1338              :     {
    1339      3697399 :       auto tcode = tree_code (code);
    1340      3697399 :       if (commutative_tree_code (tcode)
    1341      3697399 :           || commutative_ternary_tree_code (tcode))
    1342        19665 :         return 0;
    1343              :       return -1;
    1344              :     }
    1345      4528365 :   auto cfn = combined_fn (code);
    1346      4528365 :   return first_commutative_argument (associated_internal_fn (cfn, type));
    1347              : }
    1348              : 
    1349              : /* Return true if CODE is a binary operation that is associative when
    1350              :    operating on type TYPE.  */
    1351              : 
    1352              : bool
    1353        67352 : associative_binary_op_p (code_helper code, tree type)
    1354              : {
    1355        67352 :   if (code.is_tree_code ())
    1356        67300 :     return associative_tree_code (tree_code (code));
    1357           52 :   auto cfn = combined_fn (code);
    1358           52 :   return associative_binary_fn_p (associated_internal_fn (cfn, type));
    1359              : }
    1360              : 
    1361              : /* Return true if the target directly supports operation CODE on type TYPE.
    1362              :    QUERY_TYPE acts as for optab_for_tree_code.  */
    1363              : 
    1364              : bool
    1365       290441 : directly_supported_p (code_helper code, tree type, optab_subtype query_type)
    1366              : {
    1367       290441 :   if (code.is_tree_code ())
    1368              :     {
    1369       285621 :       direct_optab optab = optab_for_tree_code (tree_code (code), type,
    1370              :                                                 query_type);
    1371       285621 :       return (optab != unknown_optab
    1372       285621 :               && optab_handler (optab, TYPE_MODE (type)) != CODE_FOR_nothing);
    1373              :     }
    1374         4820 :   gcc_assert (query_type == optab_default
    1375              :               || (query_type == optab_vector && VECTOR_TYPE_P (type))
    1376              :               || (query_type == optab_scalar && !VECTOR_TYPE_P (type)));
    1377         4820 :   internal_fn ifn = associated_internal_fn (combined_fn (code), type);
    1378         4820 :   return (direct_internal_fn_p (ifn)
    1379         4820 :           && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED));
    1380              : }
    1381              : 
    1382              : /* As above, overloading the function for conversion-type optabs.  */
    1383              : bool
    1384         3614 : directly_supported_p (code_helper code, tree otype, tree itype,
    1385              :                       optab_subtype query_type)
    1386              : {
    1387         3614 :   if (code.is_tree_code ())
    1388              :     {
    1389         3614 :       convert_optab optab = optab_for_tree_code (tree_code (code), itype,
    1390              :                                                 query_type);
    1391         3614 :       return (optab != unknown_optab
    1392         7228 :               && convert_optab_handler (optab, TYPE_MODE (otype),
    1393         3614 :                                         TYPE_MODE (itype)) != CODE_FOR_nothing);
    1394              :     }
    1395            0 :   gcc_assert (query_type == optab_default
    1396              :               || (query_type == optab_vector && VECTOR_TYPE_P (itype))
    1397              :               || (query_type == optab_scalar && !VECTOR_TYPE_P (itype)));
    1398            0 :   internal_fn ifn = associated_internal_fn (combined_fn (code), itype);
    1399            0 :   return (direct_internal_fn_p (ifn)
    1400            0 :           && direct_internal_fn_supported_p (ifn, tree_pair (otype, itype),
    1401              :                                              OPTIMIZE_FOR_SPEED));
    1402              : }
    1403              : 
    1404              : 
    1405              : /* A wrapper around the internal-fn.cc versions of get_conditional_internal_fn
    1406              :    for a code_helper CODE operating on type TYPE.  */
    1407              : 
    1408              : internal_fn
    1409         5089 : get_conditional_internal_fn (code_helper code, tree type)
    1410              : {
    1411         5089 :   if (code.is_tree_code ())
    1412         5089 :     return get_conditional_internal_fn (tree_code (code));
    1413            0 :   auto cfn = combined_fn (code);
    1414            0 :   return get_conditional_internal_fn (associated_internal_fn (cfn, type));
    1415              : }
    1416              : 
    1417              : /* Find the operand which is different between ARG0_OP and ARG1_OP.
    1418              :    Returns the operand num where the difference is.
    1419              :    Set NEWARG0 and NEWARG1 from the different argument.
    1420              :    Returns -1 if none is found.
    1421              :    If ARG0_OP/ARG1_OP is commutative also try swapping the
    1422              :    two commutative operands and return the operand number where
    1423              :    the difference happens in ARG0_OP. */
    1424              : 
    1425              : int
    1426        29696 : find_different_opnum (const gimple_match_op &arg0_op,
    1427              :                       const gimple_match_op &arg1_op,
    1428              :                       tree *new_arg0, tree *new_arg1)
    1429              : {
    1430        29696 :   unsigned opnum = -1;
    1431        29696 :   unsigned first;
    1432        29696 :   first = first_commutative_argument (arg1_op.code, arg1_op.type);
    1433        68690 :   for (unsigned i = 0; i < arg0_op.num_ops; i++)
    1434              :     {
    1435        54437 :       if (!operand_equal_for_phi_arg_p (arg0_op.ops[i],
    1436        54437 :                                         arg1_op.ops[i]))
    1437              :         {
    1438              :           /* Can handle only one non equal operand. */
    1439        43158 :           if (opnum != -1u)
    1440              :             {
    1441              :               /* Though if opnum is right before i and opnum is equal
    1442              :                  to the first communtative argument, handle communtative
    1443              :                  specially. */
    1444        15443 :               if (i == opnum + 1 && opnum == first)
    1445        11325 :                 goto commutative;
    1446              :               return -1;
    1447              :             }
    1448              :           opnum = i;
    1449              :         }
    1450              :   }
    1451              :   /* If all operands are equal only do this is there was single
    1452              :      operand.  */
    1453        14253 :   if (opnum == -1u)
    1454              :     {
    1455         1981 :       if (arg0_op.num_ops != 1)
    1456              :         return -1;
    1457              :       opnum = 0;
    1458              :     }
    1459        12488 :   *new_arg0 = arg0_op.ops[opnum];
    1460        12488 :   *new_arg1 = arg1_op.ops[opnum];
    1461        12488 :   return opnum;
    1462              : 
    1463              : /* Handle commutative operations. */
    1464        11325 : commutative:
    1465        11325 :   gcc_assert (first != -1u);
    1466              : 
    1467              :   /* Check the rest of the arguments to make sure they are the same. */
    1468        11325 :   for (unsigned i = first + 2; i < arg0_op.num_ops; i++)
    1469            0 :     if (!operand_equal_for_phi_arg_p (arg0_op.ops[i],
    1470            0 :                                       arg1_op.ops[i]))
    1471              :       return -1;
    1472              : 
    1473              :   /* If the arg0[first+1] and arg1[first] are the same
    1474              :      then the one which is different is arg0[first] and arg1[first+1]
    1475              :      return first since this is based on arg0.  */
    1476        11325 :   if (operand_equal_for_phi_arg_p (arg0_op.ops[first + 1],
    1477        11325 :                                    arg1_op.ops[first]))
    1478              :     {
    1479           76 :        *new_arg0 = arg0_op.ops[first];
    1480           76 :        *new_arg1 = arg1_op.ops[first + 1];
    1481           76 :        return first;
    1482              :     }
    1483              :   /* If the arg0[first] and arg1[first+1] are the same
    1484              :      then the one which is different is arg0[first+1] and arg1[first]
    1485              :      return first+1 since this is based on arg0.  */
    1486        11249 :   if (operand_equal_for_phi_arg_p (arg0_op.ops[first],
    1487        11249 :                                    arg1_op.ops[first + 1]))
    1488              :     {
    1489          261 :        *new_arg0 = arg0_op.ops[first + 1];
    1490          261 :        *new_arg1 = arg1_op.ops[first];
    1491          261 :        return first + 1;
    1492              :     }
    1493              :   return -1;
    1494              : }
        

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.