LCOV - code coverage report
Current view: top level - gcc - gimple-isel.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.9 % 641 589
Test Date: 2025-11-22 14:42:49 Functions: 100.0 % 10 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Schedule GIMPLE vector statements.
       2                 :             :    Copyright (C) 2020-2025 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
       7                 :             : under the terms of the GNU General Public License as published by the
       8                 :             : Free Software Foundation; either version 3, or (at your option) any
       9                 :             : later version.
      10                 :             : 
      11                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT
      12                 :             : ANY 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 "rtl.h"
      25                 :             : #include "tree.h"
      26                 :             : #include "gimple.h"
      27                 :             : #include "tree-pass.h"
      28                 :             : #include "ssa.h"
      29                 :             : #include "expmed.h"
      30                 :             : #include "optabs-tree.h"
      31                 :             : #include "tree-eh.h"
      32                 :             : #include "gimple-iterator.h"
      33                 :             : #include "gimplify-me.h"
      34                 :             : #include "gimplify.h"
      35                 :             : #include "tree-cfg.h"
      36                 :             : #include "bitmap.h"
      37                 :             : #include "tree-ssa-dce.h"
      38                 :             : #include "memmodel.h"
      39                 :             : #include "optabs.h"
      40                 :             : #include "gimple-fold.h"
      41                 :             : #include "internal-fn.h"
      42                 :             : #include "fold-const.h"
      43                 :             : 
      44                 :             : /* Expand all ARRAY_REF(VIEW_CONVERT_EXPR) gimple assignments into calls to
      45                 :             :    internal function based on vector type of selected expansion.
      46                 :             : 
      47                 :             :    For vec_set:
      48                 :             : 
      49                 :             :      VIEW_CONVERT_EXPR<int[4]>(u)[_1] = i_4(D);
      50                 :             :    =>
      51                 :             :      _7 = u;
      52                 :             :      _8 = .VEC_SET (_7, i_4(D), _1);
      53                 :             :      u = _8;
      54                 :             : 
      55                 :             :    For vec_extract:
      56                 :             : 
      57                 :             :       _3 = VIEW_CONVERT_EXPR<intD.1[4]>(vD.2208)[idx_2(D)];
      58                 :             :    =>
      59                 :             :       _4 = vD.2208;
      60                 :             :       _3 = .VEC_EXTRACT (_4, idx_2(D));  */
      61                 :             : 
      62                 :             : static bool
      63                 :    96806733 : gimple_expand_vec_set_extract_expr (struct function *fun,
      64                 :             :                                     gimple_stmt_iterator *gsi)
      65                 :             : {
      66                 :    96806733 :   gcall *new_stmt = NULL;
      67                 :    96806733 :   gassign *ass_stmt = NULL;
      68                 :    96806733 :   bool cfg_changed = false;
      69                 :             : 
      70                 :             :   /* Only consider code == GIMPLE_ASSIGN.  */
      71                 :   128838542 :   gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
      72                 :    32041724 :   if (!stmt)
      73                 :             :     return false;
      74                 :             : 
      75                 :    32041724 :   bool is_extract = false;
      76                 :             : 
      77                 :    32041724 :   tree lhs = gimple_assign_lhs (stmt);
      78                 :    32041724 :   tree rhs = gimple_assign_rhs1 (stmt);
      79                 :    32041724 :   tree val, ref;
      80                 :    32041724 :   if (TREE_CODE (lhs) == ARRAY_REF)
      81                 :             :     {
      82                 :             :       /* Assume it is a vec_set.  */
      83                 :             :       val = rhs;
      84                 :             :       ref = lhs;
      85                 :             :     }
      86                 :    31430771 :   else if (TREE_CODE (rhs) == ARRAY_REF)
      87                 :             :     {
      88                 :             :       /* vec_extract.  */
      89                 :             :       is_extract = true;
      90                 :             :       val = lhs;
      91                 :             :       ref = rhs;
      92                 :             :     }
      93                 :             :   else
      94                 :             :     return false;
      95                 :             : 
      96                 :     1173651 :   tree op0 = TREE_OPERAND (ref, 0);
      97                 :       32093 :   if (TREE_CODE (op0) == VIEW_CONVERT_EXPR && DECL_P (TREE_OPERAND (op0, 0))
      98                 :       26767 :       && VECTOR_TYPE_P (TREE_TYPE (TREE_OPERAND (op0, 0)))
      99                 :     1193525 :       && TYPE_MODE (TREE_TYPE (ref))
     100                 :        9937 :            == TYPE_MODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (op0, 0)))))
     101                 :             :     {
     102                 :        9933 :       tree pos = TREE_OPERAND (ref, 1);
     103                 :             : 
     104                 :        9933 :       tree view_op0 = TREE_OPERAND (op0, 0);
     105                 :             : 
     106                 :        9933 :       tree idx = TREE_OPERAND (ref, 1);
     107                 :             :       // if index is a constant, then check the bounds
     108                 :        9933 :       poly_uint64 idx_poly;
     109                 :        9933 :       if (poly_int_tree_p (idx, &idx_poly))
     110                 :             :         {
     111                 :          31 :           poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (view_op0));
     112                 :          31 :           if (known_gt (idx_poly, nelts))
     113                 :          18 :             return false;
     114                 :             :         }
     115                 :        9915 :       machine_mode outermode = TYPE_MODE (TREE_TYPE (view_op0));
     116                 :        9915 :       machine_mode extract_mode = TYPE_MODE (TREE_TYPE (ref));
     117                 :             : 
     118                 :        9915 :       if ((auto_var_in_fn_p (view_op0, fun->decl)
     119                 :        1307 :            || (VAR_P (view_op0) && DECL_HARD_REGISTER (view_op0)))
     120                 :        8618 :           && !TREE_ADDRESSABLE (view_op0)
     121                 :       16804 :           && ((!is_extract && can_vec_set_var_idx_p (outermode))
     122                 :             :               || (is_extract
     123                 :        6750 :                   && can_vec_extract_var_idx_p (outermode, extract_mode))))
     124                 :             :         {
     125                 :         122 :           location_t loc = gimple_location (stmt);
     126                 :         122 :           tree var_src = make_ssa_name (TREE_TYPE (view_op0));
     127                 :             : 
     128                 :         122 :           ass_stmt = gimple_build_assign (var_src, view_op0);
     129                 :         244 :           gimple_set_vuse (ass_stmt, gimple_vuse (stmt));
     130                 :         122 :           gimple_set_location (ass_stmt, loc);
     131                 :         122 :           gsi_insert_before (gsi, ass_stmt, GSI_SAME_STMT);
     132                 :             : 
     133                 :         122 :           if (!is_extract)
     134                 :             :             {
     135                 :         122 :               tree var_dst = make_ssa_name (TREE_TYPE (view_op0));
     136                 :             : 
     137                 :         122 :               new_stmt = gimple_build_call_internal (IFN_VEC_SET, 3, var_src,
     138                 :             :                                                      val, pos);
     139                 :             : 
     140                 :         122 :               gimple_call_set_lhs (new_stmt, var_dst);
     141                 :         122 :               gimple_set_location (new_stmt, loc);
     142                 :         122 :               gsi_insert_before (gsi, new_stmt, GSI_SAME_STMT);
     143                 :             : 
     144                 :         122 :               ass_stmt = gimple_build_assign (view_op0, var_dst);
     145                 :         122 :               gimple_set_location (ass_stmt, loc);
     146                 :         122 :               gimple_move_vops (ass_stmt, stmt);
     147                 :         122 :               gsi_insert_before (gsi, ass_stmt, GSI_SAME_STMT);
     148                 :             : 
     149                 :         122 :               basic_block bb = gimple_bb (stmt);
     150                 :         122 :               if (gsi_remove (gsi, true)
     151                 :         122 :                   && gimple_purge_dead_eh_edges (bb))
     152                 :             :                 cfg_changed = true;
     153                 :         122 :               *gsi = gsi_for_stmt (ass_stmt);
     154                 :             :             }
     155                 :             :           else
     156                 :             :             {
     157                 :           0 :               new_stmt
     158                 :           0 :                 = gimple_build_call_internal (IFN_VEC_EXTRACT, 2, var_src, pos);
     159                 :           0 :               gimple_call_set_lhs (new_stmt, lhs);
     160                 :             : 
     161                 :           0 :               gsi_replace (gsi, new_stmt, true);
     162                 :           0 :               cfg_changed = true;
     163                 :             :             }
     164                 :             :         }
     165                 :             :     }
     166                 :             : 
     167                 :             :   return cfg_changed;
     168                 :             : }
     169                 :             : 
     170                 :             : /* Expand all VEC_COND_EXPR gimple assignments into calls to internal
     171                 :             :    function based on type of selected expansion.  */
     172                 :             : 
     173                 :             : static gimple *
     174                 :    96806733 : gimple_expand_vec_cond_expr (gimple_stmt_iterator *gsi)
     175                 :             : {
     176                 :    96806733 :   tree lhs, op0a = NULL_TREE;
     177                 :    96806733 :   enum tree_code code;
     178                 :    96806733 :   enum tree_code tcode;
     179                 :             : 
     180                 :             :   /* Only consider code == GIMPLE_ASSIGN.  */
     181                 :    96806733 :   gassign *stmt = dyn_cast<gassign *> (gsi_stmt (*gsi));
     182                 :    32050491 :   if (!stmt)
     183                 :             :     return NULL;
     184                 :             : 
     185                 :    32050491 :   code = gimple_assign_rhs_code (stmt);
     186                 :    32050491 :   if (code != VEC_COND_EXPR)
     187                 :             :     return NULL;
     188                 :             : 
     189                 :       19104 :   tree op0 = gimple_assign_rhs1 (stmt);
     190                 :       19104 :   tree op1 = gimple_assign_rhs2 (stmt);
     191                 :       19104 :   tree op2 = gimple_assign_rhs3 (stmt);
     192                 :       19104 :   lhs = gimple_assign_lhs (stmt);
     193                 :       19104 :   machine_mode mode = TYPE_MODE (TREE_TYPE (lhs));
     194                 :             : 
     195                 :             :   /* Lower mask typed, non-vector mode VEC_COND_EXPRs to bitwise operations.
     196                 :             :      Those can end up generated by folding and at least for integer mode masks
     197                 :             :      we cannot expect vcond expanders to exist.  We lower a ? b : c
     198                 :             :      to (b & a) | (c & ~a).  */
     199                 :       38208 :   if (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (lhs))
     200                 :       19105 :       && !VECTOR_MODE_P (mode))
     201                 :             :     {
     202                 :           0 :       gcc_assert (types_compatible_p (TREE_TYPE (op0), TREE_TYPE (op1)));
     203                 :           0 :       gimple_seq stmts = NULL;
     204                 :           0 :       tree type = TREE_TYPE (lhs);
     205                 :           0 :       location_t loc = gimple_location (stmt);
     206                 :           0 :       tree tem0 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op1, op0);
     207                 :           0 :       tree tem1 = gimple_build (&stmts, loc, BIT_NOT_EXPR, type, op0);
     208                 :           0 :       tree tem2 = gimple_build (&stmts, loc, BIT_AND_EXPR, type, op2, tem1);
     209                 :           0 :       tree tem3 = gimple_build (&stmts, loc, BIT_IOR_EXPR, type, tem0, tem2);
     210                 :           0 :       gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
     211                 :           0 :       return gimple_build_assign (lhs, tem3);
     212                 :             :     }
     213                 :             : 
     214                 :       19104 :   bool can_compute_op0 = true;
     215                 :       19104 :   gcc_assert (!COMPARISON_CLASS_P (op0));
     216                 :       19104 :   if (TREE_CODE (op0) == SSA_NAME)
     217                 :             :     {
     218                 :       17816 :       gassign *def_stmt = dyn_cast<gassign *> (SSA_NAME_DEF_STMT (op0));
     219                 :       17806 :       if (def_stmt)
     220                 :             :         {
     221                 :       17806 :           tcode = gimple_assign_rhs_code (def_stmt);
     222                 :       17806 :           op0a = gimple_assign_rhs1 (def_stmt);
     223                 :             : 
     224                 :       17806 :           tree op0_type = TREE_TYPE (op0);
     225                 :       17806 :           tree op0a_type = TREE_TYPE (op0a);
     226                 :       17806 :           if (TREE_CODE_CLASS (tcode) == tcc_comparison)
     227                 :       13295 :             can_compute_op0 = expand_vec_cmp_expr_p (op0a_type, op0_type,
     228                 :             :                                                      tcode);
     229                 :       13295 :           gcc_assert (can_compute_op0);
     230                 :             : 
     231                 :       17806 :           if (can_compute_op0
     232                 :       17806 :               && TYPE_MODE (TREE_TYPE (lhs)) == TYPE_MODE (TREE_TYPE (op0)))
     233                 :             :             {
     234                 :             :               /* Assuming c = x CMP y.  */
     235                 :       13094 :               bool op1_minus_onep = integer_minus_onep (op1);
     236                 :       13094 :               bool op2_zerop = integer_zerop (op2);
     237                 :       13094 :               tree vtype = TREE_TYPE (lhs);
     238                 :       13094 :               machine_mode vmode = TYPE_MODE (vtype);
     239                 :             :               /* Try to fold r = c ? -1 : 0 to r = c.  */
     240                 :       13094 :               if (op1_minus_onep && op2_zerop)
     241                 :             :                 {
     242                 :        3549 :                   tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
     243                 :        3549 :                   return gimple_build_assign (lhs, conv_op);
     244                 :             :                 }
     245                 :             :               /* Try to fold r = c ? -1 : z to r = c | z, or
     246                 :             :                  r = c ? c : z.  */
     247                 :        9545 :               if (op1_minus_onep)
     248                 :             :                 {
     249                 :          16 :                   tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
     250                 :          16 :                   tree new_op1 = make_ssa_name (vtype);
     251                 :          16 :                   gassign *new_stmt = gimple_build_assign (new_op1, conv_op);
     252                 :          16 :                   gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
     253                 :          16 :                   if (optab_handler (ior_optab, vmode) != CODE_FOR_nothing)
     254                 :             :                     /* r = c | z */
     255                 :          16 :                     return gimple_build_assign (lhs, BIT_IOR_EXPR, new_op1,
     256                 :          16 :                                                 op2);
     257                 :             :                   /* r = c ? c : z */
     258                 :             :                   op1 = new_op1;
     259                 :             :                 }
     260                 :             :               /* Try to fold r = c ? z : 0 to r = c & z, or
     261                 :             :                  r = c ? z : c.  */
     262                 :        9529 :               else if (op2_zerop)
     263                 :             :                 {
     264                 :        6772 :                   tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
     265                 :        6772 :                   tree new_op2 = make_ssa_name (vtype);
     266                 :        6772 :                   gassign *new_stmt = gimple_build_assign (new_op2, conv_op);
     267                 :        6772 :                   gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
     268                 :        6772 :                   if (optab_handler (and_optab, vmode) != CODE_FOR_nothing)
     269                 :             :                     /* r = c | z */
     270                 :        6772 :                     return gimple_build_assign (lhs, BIT_AND_EXPR, new_op2,
     271                 :        6772 :                                                 op1);
     272                 :             :                   /* r = c ? z : c */
     273                 :             :                   op2 = new_op2;
     274                 :             :                 }
     275                 :        2757 :               bool op1_zerop = integer_zerop (op1);
     276                 :        2757 :               bool op2_minus_onep = integer_minus_onep (op2);
     277                 :             :               /* Try to fold r = c ? 0 : z to r = .BIT_ANDN (z, c).  */
     278                 :        2757 :               if (op1_zerop
     279                 :        2757 :                   && (direct_internal_fn_supported_p (IFN_BIT_ANDN, vtype,
     280                 :             :                                                       OPTIMIZE_FOR_BOTH)))
     281                 :             :                 {
     282                 :          74 :                   tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
     283                 :          74 :                   tree new_op = make_ssa_name (vtype);
     284                 :          74 :                   gassign *new_stmt = gimple_build_assign (new_op, conv_op);
     285                 :          74 :                   gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
     286                 :          74 :                   return gimple_build_call_internal (IFN_BIT_ANDN, 2, op2,
     287                 :          74 :                                                      new_op);
     288                 :             :                 }
     289                 :             :               /* Try to fold r = c ? z : -1 to r = .BIT_IORN (z, c).  */
     290                 :        2683 :               else if (op2_minus_onep
     291                 :        2683 :                        && (direct_internal_fn_supported_p (IFN_BIT_IORN, vtype,
     292                 :             :                                                            OPTIMIZE_FOR_BOTH)))
     293                 :             :                 {
     294                 :           0 :                   tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
     295                 :           0 :                   tree new_op = make_ssa_name (vtype);
     296                 :           0 :                   gassign *new_stmt = gimple_build_assign (new_op, conv_op);
     297                 :           0 :                   gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
     298                 :           0 :                   return gimple_build_call_internal (IFN_BIT_IORN, 2, op1,
     299                 :           0 :                                                      new_op);
     300                 :             :                 }
     301                 :             :             }
     302                 :             :         }
     303                 :             :     }
     304                 :             : 
     305                 :        8693 :   gcc_assert (VECTOR_BOOLEAN_TYPE_P (TREE_TYPE (op0)));
     306                 :       17386 :   gcc_assert (get_vcond_mask_icode (mode, TYPE_MODE (TREE_TYPE (op0)))
     307                 :             :               != CODE_FOR_nothing);
     308                 :        8693 :   return gimple_build_call_internal (IFN_VCOND_MASK, 3, op0, op1, op2);
     309                 :             : }
     310                 :             : 
     311                 :             : /* Duplicate COND_EXPR condition defs of STMT located in BB when they are
     312                 :             :    comparisons so RTL expansion with the help of TER
     313                 :             :    can perform better if conversion.  */
     314                 :             : static void
     315                 :      557250 : maybe_duplicate_comparison (gassign *stmt, basic_block bb)
     316                 :             : {
     317                 :      557250 :   imm_use_iterator imm_iter;
     318                 :      557250 :   use_operand_p use_p;
     319                 :      557250 :   auto_vec<gassign *, 4> cond_exprs;
     320                 :      557250 :   tree lhs = gimple_assign_lhs (stmt);
     321                 :      557250 :   unsigned cnt = 0;
     322                 :             : 
     323                 :             :   /* This is should not be used for -O0 nor it is not useful
     324                 :             :      when ter is turned off. */
     325                 :      557250 :   if (!optimize || !flag_tree_ter)
     326                 :             :     return;
     327                 :             : 
     328                 :     1332804 :   FOR_EACH_IMM_USE_FAST (use_p, imm_iter, lhs)
     329                 :             :     {
     330                 :      463572 :       if (is_gimple_debug (USE_STMT (use_p)))
     331                 :       11425 :         continue;
     332                 :      452147 :       cnt++;
     333                 :             :       /* Add the use statement if it was a cond_expr.  */
     334                 :      452147 :       if (gimple_bb (USE_STMT (use_p)) == bb
     335                 :      403846 :           && is_gimple_assign (USE_STMT (use_p))
     336                 :      384779 :           && gimple_assign_rhs_code (USE_STMT (use_p)) == COND_EXPR
     337                 :      467536 :           && gimple_assign_rhs1_ptr (USE_STMT (use_p)) == use_p->use)
     338                 :       14979 :         cond_exprs.safe_push (as_a <gassign *> (USE_STMT (use_p)));
     339                 :      434616 :     }
     340                 :             : 
     341                 :             :   /* If the comparison has 0 or 1 uses, no reason to do anything. */
     342                 :      434616 :   if (cnt <= 1)
     343                 :             :     return;
     344                 :             : 
     345                 :             :   /* If we only use the expression inside cond_exprs in that BB, we don't
     346                 :             :      need to duplicate for one of them so pop the top. */
     347                 :       23128 :   if (cond_exprs.length () == cnt)
     348                 :         130 :     cond_exprs.pop();
     349                 :             : 
     350                 :       23506 :   while (!cond_exprs.is_empty())
     351                 :             :     {
     352                 :         378 :       auto old_top = cond_exprs.pop();
     353                 :         378 :       gassign *copy = as_a <gassign *> (gimple_copy (stmt));
     354                 :         378 :       tree new_def = duplicate_ssa_name (lhs, copy);
     355                 :         378 :       gimple_assign_set_lhs (copy, new_def);
     356                 :         378 :       auto gsi2 = gsi_for_stmt (old_top);
     357                 :         378 :       gsi_insert_before (&gsi2, copy, GSI_SAME_STMT);
     358                 :         378 :       gimple_assign_set_rhs1 (old_top, new_def);
     359                 :         378 :       update_stmt (old_top);
     360                 :             :     }
     361                 :      557250 : }
     362                 :             : 
     363                 :             : /* match.pd function to match atomic_bit_test_and pattern which
     364                 :             :    has nop_convert:
     365                 :             :      _1 = __atomic_fetch_or_4 (&v, 1, 0);
     366                 :             :      _2 = (int) _1;
     367                 :             :      _5 = _2 & 1;
     368                 :             :  */
     369                 :             : extern bool gimple_nop_atomic_bit_test_and_p (tree, tree *,
     370                 :             :                                               tree (*) (tree));
     371                 :             : extern bool gimple_nop_convert (tree, tree*, tree (*) (tree));
     372                 :             : 
     373                 :             : namespace {
     374                 :             : 
     375                 :             : const pass_data pass_data_gimple_isel =
     376                 :             : {
     377                 :             :   GIMPLE_PASS, /* type */
     378                 :             :   "isel", /* name */
     379                 :             :   OPTGROUP_VEC, /* optinfo_flags */
     380                 :             :   TV_NONE, /* tv_id */
     381                 :             :   PROP_cfg, /* properties_required */
     382                 :             :   0, /* properties_provided */
     383                 :             :   0, /* properties_destroyed */
     384                 :             :   0, /* todo_flags_start */
     385                 :             :   TODO_update_ssa, /* todo_flags_finish */
     386                 :             : };
     387                 :             : 
     388                 :             : class pass_gimple_isel : public gimple_opt_pass
     389                 :             : {
     390                 :             : public:
     391                 :      289302 :   pass_gimple_isel (gcc::context *ctxt)
     392                 :      578604 :     : gimple_opt_pass (pass_data_gimple_isel, ctxt)
     393                 :             :   {}
     394                 :             : 
     395                 :             :   /* opt_pass methods: */
     396                 :     1472888 :   bool gate (function *) final override
     397                 :             :     {
     398                 :     1472888 :       return true;
     399                 :             :     }
     400                 :             : 
     401                 :             :   unsigned int execute (function *fun) final override;
     402                 :             : }; // class pass_gimple_isel
     403                 :             : 
     404                 :             : 
     405                 :             : 
     406                 :             : /* Convert
     407                 :             :    _1 = __atomic_fetch_or_* (ptr_6, 1, _3);
     408                 :             :    _7 = ~_1;
     409                 :             :    _5 = (_Bool) _7;
     410                 :             :    to
     411                 :             :    _1 = __atomic_fetch_or_* (ptr_6, 1, _3);
     412                 :             :    _8 = _1 & 1;
     413                 :             :    _5 = _8 == 0;
     414                 :             :    and convert
     415                 :             :    _1 = __atomic_fetch_and_* (ptr_6, ~1, _3);
     416                 :             :    _7 = ~_1;
     417                 :             :    _4 = (_Bool) _7;
     418                 :             :    to
     419                 :             :    _1 = __atomic_fetch_and_* (ptr_6, ~1, _3);
     420                 :             :    _8 = _1 & 1;
     421                 :             :    _4 = (_Bool) _8;
     422                 :             : 
     423                 :             :    USE_STMT is the gimplt statement which uses the return value of
     424                 :             :    __atomic_fetch_or_*.  LHS is the return value of __atomic_fetch_or_*.
     425                 :             :    MASK is the mask passed to __atomic_fetch_or_*.
     426                 :             :  */
     427                 :             : 
     428                 :             : static gimple *
     429                 :          14 : convert_atomic_bit_not (enum internal_fn fn, gimple *use_stmt,
     430                 :             :                         tree lhs, tree mask)
     431                 :             : {
     432                 :          14 :   tree and_mask;
     433                 :          14 :   if (fn == IFN_ATOMIC_BIT_TEST_AND_RESET)
     434                 :             :     {
     435                 :             :       /* MASK must be ~1.  */
     436                 :           8 :       if (!operand_equal_p (build_int_cst (TREE_TYPE (lhs),
     437                 :             :                                            ~HOST_WIDE_INT_1), mask, 0))
     438                 :             :         return nullptr;
     439                 :           8 :       and_mask = build_int_cst (TREE_TYPE (lhs), 1);
     440                 :             :     }
     441                 :             :   else
     442                 :             :     {
     443                 :             :       /* MASK must be 1.  */
     444                 :           6 :       if (!operand_equal_p (build_int_cst (TREE_TYPE (lhs), 1), mask, 0))
     445                 :             :         return nullptr;
     446                 :             :       and_mask = mask;
     447                 :             :     }
     448                 :             : 
     449                 :          14 :   tree use_lhs = gimple_assign_lhs (use_stmt);
     450                 :             : 
     451                 :          14 :   use_operand_p use_p;
     452                 :          14 :   gimple *use_not_stmt;
     453                 :             : 
     454                 :          14 :   if (!single_imm_use (use_lhs, &use_p, &use_not_stmt)
     455                 :          14 :       || !is_gimple_assign (use_not_stmt))
     456                 :             :     return nullptr;
     457                 :             : 
     458                 :          14 :   if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (use_not_stmt)))
     459                 :             :     return nullptr;
     460                 :             : 
     461                 :          14 :   tree use_not_lhs = gimple_assign_lhs (use_not_stmt);
     462                 :          14 :   if (TREE_CODE (TREE_TYPE (use_not_lhs)) != BOOLEAN_TYPE)
     463                 :             :     return nullptr;
     464                 :             : 
     465                 :          14 :   gimple_stmt_iterator gsi;
     466                 :          14 :   tree var = make_ssa_name (TREE_TYPE (lhs));
     467                 :             :   /* use_stmt need to be removed after use_nop_stmt,
     468                 :             :      so use_lhs can be released.  */
     469                 :          14 :   gimple *use_stmt_removal = use_stmt;
     470                 :          14 :   use_stmt = gimple_build_assign (var, BIT_AND_EXPR, lhs, and_mask);
     471                 :          14 :   gsi = gsi_for_stmt (use_not_stmt);
     472                 :          14 :   gsi_insert_before (&gsi, use_stmt, GSI_NEW_STMT);
     473                 :          14 :   lhs = gimple_assign_lhs (use_not_stmt);
     474                 :          14 :   gimple *g = gimple_build_assign (lhs, EQ_EXPR, var,
     475                 :          14 :                                    build_zero_cst (TREE_TYPE (mask)));
     476                 :          14 :   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
     477                 :          14 :   gsi = gsi_for_stmt (use_not_stmt);
     478                 :          14 :   gsi_remove (&gsi, true);
     479                 :          14 :   gsi = gsi_for_stmt (use_stmt_removal);
     480                 :          14 :   gsi_remove (&gsi, true);
     481                 :          14 :   return use_stmt;
     482                 :             : }
     483                 :             : 
     484                 :             : /* Optimize
     485                 :             :      mask_2 = 1 << cnt_1;
     486                 :             :      _4 = __atomic_fetch_or_* (ptr_6, mask_2, _3);
     487                 :             :      _5 = _4 & mask_2;
     488                 :             :    to
     489                 :             :      _4 = .ATOMIC_BIT_TEST_AND_SET (ptr_6, cnt_1, 0, _3);
     490                 :             :      _5 = _4;
     491                 :             :    If _5 is only used in _5 != 0 or _5 == 0 comparisons, 1
     492                 :             :    is passed instead of 0, and the builtin just returns a zero
     493                 :             :    or 1 value instead of the actual bit.
     494                 :             :    Similarly for __sync_fetch_and_or_* (without the ", _3" part
     495                 :             :    in there), and/or if mask_2 is a power of 2 constant.
     496                 :             :    Similarly for xor instead of or, use ATOMIC_BIT_TEST_AND_COMPLEMENT
     497                 :             :    in that case.  And similarly for and instead of or, except that
     498                 :             :    the second argument to the builtin needs to be one's complement
     499                 :             :    of the mask instead of mask.  */
     500                 :             : 
     501                 :             : static bool
     502                 :        4613 : optimize_atomic_bit_test_and (gimple_stmt_iterator *gsip,
     503                 :             :                               enum internal_fn fn, bool has_model_arg,
     504                 :             :                               bool after)
     505                 :             : {
     506                 :        4613 :   gimple *call = gsi_stmt (*gsip);
     507                 :        4613 :   tree lhs = gimple_call_lhs (call);
     508                 :        4613 :   use_operand_p use_p;
     509                 :        4613 :   gimple *use_stmt;
     510                 :        4613 :   tree mask;
     511                 :        4613 :   optab optab;
     512                 :             : 
     513                 :        4613 :   if (!flag_inline_atomics
     514                 :        4613 :       || optimize_debug
     515                 :        4613 :       || !gimple_call_builtin_p (call, BUILT_IN_NORMAL)
     516                 :        4613 :       || !lhs
     517                 :        2962 :       || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)
     518                 :        2962 :       || !single_imm_use (lhs, &use_p, &use_stmt)
     519                 :        2932 :       || !is_gimple_assign (use_stmt)
     520                 :        6321 :       || !gimple_vdef (call))
     521                 :        2905 :     return false;
     522                 :             : 
     523                 :        1708 :   switch (fn)
     524                 :             :     {
     525                 :             :     case IFN_ATOMIC_BIT_TEST_AND_SET:
     526                 :             :       optab = atomic_bit_test_and_set_optab;
     527                 :             :       break;
     528                 :             :     case IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT:
     529                 :             :       optab = atomic_bit_test_and_complement_optab;
     530                 :             :       break;
     531                 :             :     case IFN_ATOMIC_BIT_TEST_AND_RESET:
     532                 :             :       optab = atomic_bit_test_and_reset_optab;
     533                 :             :       break;
     534                 :             :     default:
     535                 :             :       return false;
     536                 :             :     }
     537                 :             : 
     538                 :        1708 :   tree bit = nullptr;
     539                 :             : 
     540                 :        1708 :   mask = gimple_call_arg (call, 1);
     541                 :        1708 :   tree_code rhs_code = gimple_assign_rhs_code (use_stmt);
     542                 :        1708 :   if (rhs_code != BIT_AND_EXPR)
     543                 :             :     {
     544                 :        1416 :       if (rhs_code != NOP_EXPR && rhs_code != BIT_NOT_EXPR)
     545                 :        1259 :         return false;
     546                 :             : 
     547                 :         845 :       tree use_lhs = gimple_assign_lhs (use_stmt);
     548                 :         845 :       if (TREE_CODE (use_lhs) == SSA_NAME
     549                 :         845 :           && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_lhs))
     550                 :             :         return false;
     551                 :             : 
     552                 :         845 :       tree use_rhs = gimple_assign_rhs1 (use_stmt);
     553                 :         845 :       if (lhs != use_rhs)
     554                 :             :         return false;
     555                 :             : 
     556                 :         845 :       if (optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)))
     557                 :             :           == CODE_FOR_nothing)
     558                 :             :         return false;
     559                 :             : 
     560                 :         581 :       gimple *g;
     561                 :         581 :       gimple_stmt_iterator gsi;
     562                 :         581 :       tree var;
     563                 :         581 :       int ibit = -1;
     564                 :             : 
     565                 :         581 :       if (rhs_code == BIT_NOT_EXPR)
     566                 :             :         {
     567                 :          14 :           g = convert_atomic_bit_not (fn, use_stmt, lhs, mask);
     568                 :          14 :           if (!g)
     569                 :             :             return false;
     570                 :          14 :           use_stmt = g;
     571                 :          14 :           ibit = 0;
     572                 :             :         }
     573                 :         567 :       else if (TREE_CODE (TREE_TYPE (use_lhs)) == BOOLEAN_TYPE)
     574                 :             :         {
     575                 :          15 :           tree and_mask;
     576                 :          15 :           if (fn == IFN_ATOMIC_BIT_TEST_AND_RESET)
     577                 :             :             {
     578                 :             :               /* MASK must be ~1.  */
     579                 :           8 :               if (!operand_equal_p (build_int_cst (TREE_TYPE (lhs),
     580                 :             :                                                    ~HOST_WIDE_INT_1),
     581                 :             :                                     mask, 0))
     582                 :             :                 return false;
     583                 :             : 
     584                 :             :               /* Convert
     585                 :             :                  _1 = __atomic_fetch_and_* (ptr_6, ~1, _3);
     586                 :             :                  _4 = (_Bool) _1;
     587                 :             :                  to
     588                 :             :                  _1 = __atomic_fetch_and_* (ptr_6, ~1, _3);
     589                 :             :                  _5 = _1 & 1;
     590                 :             :                  _4 = (_Bool) _5;
     591                 :             :                */
     592                 :           8 :               and_mask = build_int_cst (TREE_TYPE (lhs), 1);
     593                 :             :             }
     594                 :             :           else
     595                 :             :             {
     596                 :           7 :               and_mask = build_int_cst (TREE_TYPE (lhs), 1);
     597                 :           7 :               if (!operand_equal_p (and_mask, mask, 0))
     598                 :             :                 return false;
     599                 :             : 
     600                 :             :               /* Convert
     601                 :             :                  _1 = __atomic_fetch_or_* (ptr_6, 1, _3);
     602                 :             :                  _4 = (_Bool) _1;
     603                 :             :                  to
     604                 :             :                  _1 = __atomic_fetch_or_* (ptr_6, 1, _3);
     605                 :             :                  _5 = _1 & 1;
     606                 :             :                  _4 = (_Bool) _5;
     607                 :             :                */
     608                 :             :             }
     609                 :          15 :           var = make_ssa_name (TREE_TYPE (use_rhs));
     610                 :          15 :           replace_uses_by (use_rhs, var);
     611                 :          15 :           g = gimple_build_assign (var, BIT_AND_EXPR, use_rhs,
     612                 :             :                                    and_mask);
     613                 :          15 :           gsi = gsi_for_stmt (use_stmt);
     614                 :          15 :           gsi_insert_before (&gsi, g, GSI_NEW_STMT);
     615                 :          15 :           use_stmt = g;
     616                 :          15 :           ibit = 0;
     617                 :             :         }
     618                 :         552 :       else if (TYPE_PRECISION (TREE_TYPE (use_lhs))
     619                 :         552 :                <= TYPE_PRECISION (TREE_TYPE (use_rhs)))
     620                 :             :         {
     621                 :         550 :           gimple *use_nop_stmt;
     622                 :         550 :           if (!single_imm_use (use_lhs, &use_p, &use_nop_stmt)
     623                 :         550 :               || (!is_gimple_assign (use_nop_stmt)
     624                 :          93 :                   && gimple_code (use_nop_stmt) != GIMPLE_COND))
     625                 :         422 :             return false;
     626                 :             :           /* Handle both
     627                 :             :              _4 = _5 < 0;
     628                 :             :              and
     629                 :             :              if (_5 < 0)
     630                 :             :            */
     631                 :         466 :           tree use_nop_lhs = nullptr;
     632                 :         466 :           rhs_code = ERROR_MARK;
     633                 :         466 :           if (is_gimple_assign (use_nop_stmt))
     634                 :             :             {
     635                 :         457 :               use_nop_lhs = gimple_assign_lhs (use_nop_stmt);
     636                 :         457 :               rhs_code = gimple_assign_rhs_code (use_nop_stmt);
     637                 :             :             }
     638                 :         466 :           if (!use_nop_lhs || rhs_code != BIT_AND_EXPR)
     639                 :             :             {
     640                 :             :               /* Also handle
     641                 :             :                  if (_5 < 0)
     642                 :             :                */
     643                 :         372 :               if (use_nop_lhs
     644                 :         363 :                   && TREE_CODE (use_nop_lhs) == SSA_NAME
     645                 :         423 :                   && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_nop_lhs))
     646                 :             :                 return false;
     647                 :         372 :               if (use_nop_lhs && rhs_code == BIT_NOT_EXPR)
     648                 :             :                 {
     649                 :             :                   /* Handle
     650                 :             :                      _7 = ~_2;
     651                 :             :                    */
     652                 :           0 :                   g = convert_atomic_bit_not (fn, use_nop_stmt, lhs,
     653                 :             :                                               mask);
     654                 :           0 :                   if (!g)
     655                 :             :                     return false;
     656                 :             :                   /* Convert
     657                 :             :                      _1 = __atomic_fetch_or_4 (ptr_6, 1, _3);
     658                 :             :                      _2 = (int) _1;
     659                 :             :                      _7 = ~_2;
     660                 :             :                      _5 = (_Bool) _7;
     661                 :             :                      to
     662                 :             :                      _1 = __atomic_fetch_or_4 (ptr_6, ~1, _3);
     663                 :             :                      _8 = _1 & 1;
     664                 :             :                      _5 = _8 == 0;
     665                 :             :                      and convert
     666                 :             :                      _1 = __atomic_fetch_and_4 (ptr_6, ~1, _3);
     667                 :             :                      _2 = (int) _1;
     668                 :             :                      _7 = ~_2;
     669                 :             :                      _5 = (_Bool) _7;
     670                 :             :                      to
     671                 :             :                      _1 = __atomic_fetch_and_4 (ptr_6, 1, _3);
     672                 :             :                      _8 = _1 & 1;
     673                 :             :                      _5 = _8 == 0;
     674                 :             :                    */
     675                 :           0 :                   gsi = gsi_for_stmt (use_stmt);
     676                 :           0 :                   gsi_remove (&gsi, true);
     677                 :           0 :                   use_stmt = g;
     678                 :           0 :                   ibit = 0;
     679                 :             :                 }
     680                 :             :               else
     681                 :             :                 {
     682                 :         372 :                   tree cmp_rhs1, cmp_rhs2;
     683                 :         372 :                   if (use_nop_lhs)
     684                 :             :                     {
     685                 :             :                       /* Handle
     686                 :             :                          _4 = _5 < 0;
     687                 :             :                        */
     688                 :         363 :                       if (TREE_CODE (TREE_TYPE (use_nop_lhs))
     689                 :             :                           != BOOLEAN_TYPE)
     690                 :         422 :                         return false;
     691                 :          51 :                       cmp_rhs1 = gimple_assign_rhs1 (use_nop_stmt);
     692                 :          51 :                       cmp_rhs2 = gimple_assign_rhs2 (use_nop_stmt);
     693                 :             :                     }
     694                 :             :                   else
     695                 :             :                     {
     696                 :             :                       /* Handle
     697                 :             :                          if (_5 < 0)
     698                 :             :                        */
     699                 :           9 :                       rhs_code = gimple_cond_code (use_nop_stmt);
     700                 :           9 :                       cmp_rhs1 = gimple_cond_lhs (use_nop_stmt);
     701                 :           9 :                       cmp_rhs2 = gimple_cond_rhs (use_nop_stmt);
     702                 :             :                     }
     703                 :          60 :                   if (rhs_code != GE_EXPR && rhs_code != LT_EXPR)
     704                 :             :                     return false;
     705                 :          48 :                   if (use_lhs != cmp_rhs1)
     706                 :             :                     return false;
     707                 :          48 :                   if (!integer_zerop (cmp_rhs2))
     708                 :             :                     return false;
     709                 :             : 
     710                 :          48 :                   tree and_mask;
     711                 :             : 
     712                 :          48 :                   unsigned HOST_WIDE_INT bytes
     713                 :          48 :                     = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (use_rhs)));
     714                 :          48 :                   ibit = bytes * BITS_PER_UNIT - 1;
     715                 :          48 :                   unsigned HOST_WIDE_INT highest
     716                 :          48 :                     = HOST_WIDE_INT_1U << ibit;
     717                 :             : 
     718                 :          48 :                   if (fn == IFN_ATOMIC_BIT_TEST_AND_RESET)
     719                 :             :                     {
     720                 :             :                       /* Get the signed maximum of the USE_RHS type.  */
     721                 :          19 :                       and_mask = build_int_cst (TREE_TYPE (use_rhs),
     722                 :          19 :                                                 highest - 1);
     723                 :          19 :                       if (!operand_equal_p (and_mask, mask, 0))
     724                 :             :                         return false;
     725                 :             : 
     726                 :             :                       /* Convert
     727                 :             :                          _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
     728                 :             :                          _5 = (signed int) _1;
     729                 :             :                          _4 = _5 < 0 or _5 >= 0;
     730                 :             :                          to
     731                 :             :                          _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
     732                 :             :                          _6 = _1 & 0x80000000;
     733                 :             :                          _4 = _6 != 0 or _6 == 0;
     734                 :             :                          and convert
     735                 :             :                          _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
     736                 :             :                          _5 = (signed int) _1;
     737                 :             :                          if (_5 < 0 or _5 >= 0)
     738                 :             :                          to
     739                 :             :                          _1 = __atomic_fetch_and_4 (ptr_6, 0x7fffffff, _3);
     740                 :             :                          _6 = _1 & 0x80000000;
     741                 :             :                          if (_6 != 0 or _6 == 0)
     742                 :             :                        */
     743                 :          19 :                       and_mask = build_int_cst (TREE_TYPE (use_rhs),
     744                 :          19 :                                                 highest);
     745                 :             :                     }
     746                 :             :                   else
     747                 :             :                     {
     748                 :             :                       /* Get the signed minimum of the USE_RHS type.  */
     749                 :          29 :                       and_mask = build_int_cst (TREE_TYPE (use_rhs),
     750                 :          29 :                                                 highest);
     751                 :          29 :                       if (!operand_equal_p (and_mask, mask, 0))
     752                 :             :                         return false;
     753                 :             : 
     754                 :             :                       /* Convert
     755                 :             :                          _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
     756                 :             :                          _5 = (signed int) _1;
     757                 :             :                          _4 = _5 < 0 or _5 >= 0;
     758                 :             :                          to
     759                 :             :                          _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
     760                 :             :                          _6 = _1 & 0x80000000;
     761                 :             :                          _4 = _6 != 0 or _6 == 0;
     762                 :             :                          and convert
     763                 :             :                          _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
     764                 :             :                          _5 = (signed int) _1;
     765                 :             :                          if (_5 < 0 or _5 >= 0)
     766                 :             :                          to
     767                 :             :                          _1 = __atomic_fetch_or_4 (ptr_6, 0x80000000, _3);
     768                 :             :                          _6 = _1 & 0x80000000;
     769                 :             :                          if (_6 != 0 or _6 == 0)
     770                 :             :                        */
     771                 :             :                     }
     772                 :          36 :                   var = make_ssa_name (TREE_TYPE (use_rhs));
     773                 :          36 :                   gimple* use_stmt_removal = use_stmt;
     774                 :          36 :                   g = gimple_build_assign (var, BIT_AND_EXPR, use_rhs,
     775                 :             :                                            and_mask);
     776                 :          36 :                   gsi = gsi_for_stmt (use_nop_stmt);
     777                 :          36 :                   gsi_insert_before (&gsi, g, GSI_NEW_STMT);
     778                 :          36 :                   use_stmt = g;
     779                 :          36 :                   rhs_code = rhs_code == GE_EXPR ? EQ_EXPR : NE_EXPR;
     780                 :          36 :                   tree const_zero = build_zero_cst (TREE_TYPE (use_rhs));
     781                 :          36 :                   if (use_nop_lhs)
     782                 :          27 :                     g = gimple_build_assign (use_nop_lhs, rhs_code,
     783                 :             :                                              var, const_zero);
     784                 :             :                   else
     785                 :           9 :                     g = gimple_build_cond (rhs_code, var, const_zero,
     786                 :             :                                            nullptr, nullptr);
     787                 :          36 :                   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
     788                 :          36 :                   gsi = gsi_for_stmt (use_nop_stmt);
     789                 :          36 :                   gsi_remove (&gsi, true);
     790                 :          36 :                   gsi = gsi_for_stmt (use_stmt_removal);
     791                 :          36 :                   gsi_remove (&gsi, true);
     792                 :             :                 }
     793                 :             :             }
     794                 :             :           else
     795                 :             :             {
     796                 :          94 :               tree match_op[3];
     797                 :          94 :               gimple *g;
     798                 :          94 :               if (!gimple_nop_atomic_bit_test_and_p (use_nop_lhs,
     799                 :             :                                                      &match_op[0], NULL)
     800                 :          92 :                   || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (match_op[2])
     801                 :          92 :                   || !single_imm_use (match_op[2], &use_p, &g)
     802                 :         186 :                   || !is_gimple_assign (g))
     803                 :           2 :                 return false;
     804                 :          92 :               mask = match_op[0];
     805                 :          92 :               if (TREE_CODE (match_op[1]) == INTEGER_CST)
     806                 :             :                 {
     807                 :          48 :                   ibit = tree_log2 (match_op[1]);
     808                 :          48 :                   gcc_assert (ibit >= 0);
     809                 :             :                 }
     810                 :             :               else
     811                 :             :                 {
     812                 :          44 :                   g = SSA_NAME_DEF_STMT (match_op[1]);
     813                 :          44 :                   gcc_assert (is_gimple_assign (g));
     814                 :          44 :                   bit = gimple_assign_rhs2 (g);
     815                 :             :                 }
     816                 :             :               /* Convert
     817                 :             :                  _1 = __atomic_fetch_or_4 (ptr_6, mask, _3);
     818                 :             :                  _2 = (int) _1;
     819                 :             :                  _5 = _2 & mask;
     820                 :             :                  to
     821                 :             :                  _1 = __atomic_fetch_or_4 (ptr_6, mask, _3);
     822                 :             :                  _6 = _1 & mask;
     823                 :             :                  _5 = (int) _6;
     824                 :             :                  and convert
     825                 :             :                  _1 = ~mask_7;
     826                 :             :                  _2 = (unsigned int) _1;
     827                 :             :                  _3 = __atomic_fetch_and_4 (ptr_6, _2, 0);
     828                 :             :                  _4 = (int) _3;
     829                 :             :                  _5 = _4 & mask_7;
     830                 :             :                  to
     831                 :             :                  _1 = __atomic_fetch_and_* (ptr_6, ~mask_7, _3);
     832                 :             :                  _12 = _3 & mask_7;
     833                 :             :                  _5 = (int) _12;
     834                 :             : 
     835                 :             :                  and Convert
     836                 :             :                  _1 = __atomic_fetch_and_4 (ptr_6, ~mask, _3);
     837                 :             :                  _2 = (short int) _1;
     838                 :             :                  _5 = _2 & mask;
     839                 :             :                  to
     840                 :             :                  _1 = __atomic_fetch_and_4 (ptr_6, ~mask, _3);
     841                 :             :                  _8 = _1 & mask;
     842                 :             :                  _5 = (short int) _8;
     843                 :             :               */
     844                 :          92 :               gimple_seq stmts = NULL;
     845                 :          92 :               match_op[1] = gimple_convert (&stmts,
     846                 :          92 :                                             TREE_TYPE (use_rhs),
     847                 :             :                                             match_op[1]);
     848                 :          92 :               var = gimple_build (&stmts, BIT_AND_EXPR,
     849                 :          92 :                                   TREE_TYPE (use_rhs), use_rhs, match_op[1]);
     850                 :          92 :               gsi = gsi_for_stmt (use_stmt);
     851                 :          92 :               gsi_remove (&gsi, true);
     852                 :          92 :               release_defs (use_stmt);
     853                 :          92 :               use_stmt = gimple_seq_last_stmt (stmts);
     854                 :          92 :               gsi = gsi_for_stmt (use_nop_stmt);
     855                 :          92 :               gsi_insert_seq_before (&gsi, stmts, GSI_SAME_STMT);
     856                 :          92 :               gimple_assign_set_rhs_with_ops (&gsi, CONVERT_EXPR, var);
     857                 :          92 :               update_stmt (use_nop_stmt);
     858                 :             :             }
     859                 :             :         }
     860                 :             :       else
     861                 :             :         return false;
     862                 :             : 
     863                 :         157 :       if (!bit)
     864                 :             :         {
     865                 :         113 :           if (ibit < 0)
     866                 :           0 :             gcc_unreachable ();
     867                 :         113 :           bit = build_int_cst (TREE_TYPE (lhs), ibit);
     868                 :             :         }
     869                 :             :     }
     870                 :         292 :   else if (optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)))
     871                 :             :            == CODE_FOR_nothing)
     872                 :             :     return false;
     873                 :             : 
     874                 :         443 :   tree use_lhs = gimple_assign_lhs (use_stmt);
     875                 :         443 :   if (!use_lhs)
     876                 :             :     return false;
     877                 :             : 
     878                 :         443 :   if (!bit)
     879                 :             :     {
     880                 :         286 :       if (TREE_CODE (mask) == INTEGER_CST)
     881                 :             :         {
     882                 :         222 :           if (fn == IFN_ATOMIC_BIT_TEST_AND_RESET)
     883                 :          62 :             mask = const_unop (BIT_NOT_EXPR, TREE_TYPE (mask), mask);
     884                 :         222 :           mask = fold_convert (TREE_TYPE (lhs), mask);
     885                 :         222 :           int ibit = tree_log2 (mask);
     886                 :         222 :           if (ibit < 0)
     887                 :          16 :             return false;
     888                 :         220 :           bit = build_int_cst (TREE_TYPE (lhs), ibit);
     889                 :             :         }
     890                 :          64 :       else if (TREE_CODE (mask) == SSA_NAME)
     891                 :             :         {
     892                 :          64 :           gimple *g = SSA_NAME_DEF_STMT (mask);
     893                 :          64 :           tree match_op;
     894                 :          64 :           if (gimple_nop_convert (mask, &match_op, NULL))
     895                 :             :             {
     896                 :           3 :               mask = match_op;
     897                 :           3 :               if (TREE_CODE (mask) != SSA_NAME)
     898                 :           7 :                 return false;
     899                 :           3 :               g = SSA_NAME_DEF_STMT (mask);
     900                 :             :             }
     901                 :          64 :           if (!is_gimple_assign (g))
     902                 :             :             return false;
     903                 :             : 
     904                 :          62 :           if (fn == IFN_ATOMIC_BIT_TEST_AND_RESET)
     905                 :             :             {
     906                 :          20 :               if (gimple_assign_rhs_code (g) != BIT_NOT_EXPR)
     907                 :             :                 return false;
     908                 :          20 :               mask = gimple_assign_rhs1 (g);
     909                 :          20 :               if (TREE_CODE (mask) != SSA_NAME)
     910                 :             :                 return false;
     911                 :          20 :               g = SSA_NAME_DEF_STMT (mask);
     912                 :             :             }
     913                 :             : 
     914                 :          62 :           if (!is_gimple_assign (g)
     915                 :          57 :               || gimple_assign_rhs_code (g) != LSHIFT_EXPR
     916                 :         119 :               || !integer_onep (gimple_assign_rhs1 (g)))
     917                 :           5 :             return false;
     918                 :          57 :           bit = gimple_assign_rhs2 (g);
     919                 :             :         }
     920                 :             :       else
     921                 :             :         return false;
     922                 :             : 
     923                 :         277 :       tree cmp_mask;
     924                 :         277 :       if (gimple_assign_rhs1 (use_stmt) == lhs)
     925                 :         241 :         cmp_mask = gimple_assign_rhs2 (use_stmt);
     926                 :             :       else
     927                 :             :         cmp_mask = gimple_assign_rhs1 (use_stmt);
     928                 :             : 
     929                 :         277 :       tree match_op;
     930                 :         277 :       if (gimple_nop_convert (cmp_mask, &match_op, NULL))
     931                 :           1 :         cmp_mask = match_op;
     932                 :             : 
     933                 :         277 :       if (!operand_equal_p (cmp_mask, mask, 0))
     934                 :             :         return false;
     935                 :             :     }
     936                 :             : 
     937                 :         427 :   bool use_bool = true;
     938                 :         427 :   bool has_debug_uses = false;
     939                 :         427 :   imm_use_iterator iter;
     940                 :         427 :   gimple *g;
     941                 :             : 
     942                 :         427 :   if (SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_lhs))
     943                 :           0 :     use_bool = false;
     944                 :        1056 :   FOR_EACH_IMM_USE_STMT (g, iter, use_lhs)
     945                 :             :     {
     946                 :         428 :       enum tree_code code = ERROR_MARK;
     947                 :         428 :       tree op0 = NULL_TREE, op1 = NULL_TREE;
     948                 :         428 :       if (is_gimple_debug (g))
     949                 :             :         {
     950                 :           1 :           has_debug_uses = true;
     951                 :           1 :           continue;
     952                 :             :         }
     953                 :         427 :       else if (is_gimple_assign (g))
     954                 :         385 :         switch (gimple_assign_rhs_code (g))
     955                 :             :           {
     956                 :           0 :           case COND_EXPR:
     957                 :           0 :             op1 = gimple_assign_rhs1 (g);
     958                 :           0 :             code = TREE_CODE (op1);
     959                 :           0 :             if (TREE_CODE_CLASS (code) != tcc_comparison)
     960                 :             :               break;
     961                 :           0 :             op0 = TREE_OPERAND (op1, 0);
     962                 :           0 :             op1 = TREE_OPERAND (op1, 1);
     963                 :           0 :             break;
     964                 :         173 :           case EQ_EXPR:
     965                 :         173 :           case NE_EXPR:
     966                 :         173 :             code = gimple_assign_rhs_code (g);
     967                 :         173 :             op0 = gimple_assign_rhs1 (g);
     968                 :         173 :             op1 = gimple_assign_rhs2 (g);
     969                 :         173 :             break;
     970                 :             :           default:
     971                 :             :             break;
     972                 :             :           }
     973                 :          42 :       else if (gimple_code (g) == GIMPLE_COND)
     974                 :             :         {
     975                 :          28 :           code = gimple_cond_code (g);
     976                 :          28 :           op0 = gimple_cond_lhs (g);
     977                 :          28 :           op1 = gimple_cond_rhs (g);
     978                 :             :         }
     979                 :             : 
     980                 :         201 :       if ((code == EQ_EXPR || code == NE_EXPR)
     981                 :         201 :           && op0 == use_lhs
     982                 :         402 :           && integer_zerop (op1))
     983                 :             :         {
     984                 :         201 :           use_operand_p use_p;
     985                 :         201 :           int n = 0;
     986                 :         402 :           FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
     987                 :         201 :             n++;
     988                 :         201 :           if (n == 1)
     989                 :         201 :             continue;
     990                 :             :         }
     991                 :             : 
     992                 :             :       use_bool = false;
     993                 :             :       break;
     994                 :         427 :     }
     995                 :             : 
     996                 :         427 :   tree new_lhs = make_ssa_name (TREE_TYPE (lhs));
     997                 :         427 :   tree flag = build_int_cst (TREE_TYPE (lhs), use_bool);
     998                 :         427 :   if (has_model_arg)
     999                 :         296 :     g = gimple_build_call_internal (fn, 5, gimple_call_arg (call, 0),
    1000                 :             :                                     bit, flag, gimple_call_arg (call, 2),
    1001                 :             :                                     gimple_call_fn (call));
    1002                 :             :   else
    1003                 :         131 :     g = gimple_build_call_internal (fn, 4, gimple_call_arg (call, 0),
    1004                 :             :                                     bit, flag, gimple_call_fn (call));
    1005                 :         427 :   gimple_call_set_lhs (g, new_lhs);
    1006                 :         427 :   gimple_set_location (g, gimple_location (call));
    1007                 :         427 :   gimple_move_vops (g, call);
    1008                 :         427 :   bool throws = stmt_can_throw_internal (cfun, call);
    1009                 :         427 :   gimple_call_set_nothrow (as_a <gcall *> (g),
    1010                 :         427 :                            gimple_call_nothrow_p (as_a <gcall *> (call)));
    1011                 :         427 :   gimple_stmt_iterator gsi = *gsip;
    1012                 :         427 :   gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    1013                 :         427 :   edge e = NULL;
    1014                 :         427 :   if (throws)
    1015                 :             :     {
    1016                 :          75 :       maybe_clean_or_replace_eh_stmt (call, g);
    1017                 :          75 :       if (after || (use_bool && has_debug_uses))
    1018                 :           9 :         e = find_fallthru_edge (gsi_bb (gsi)->succs);
    1019                 :             :     }
    1020                 :         427 :   if (after)
    1021                 :             :     {
    1022                 :             :       /* The internal function returns the value of the specified bit
    1023                 :             :          before the atomic operation.  If we are interested in the value
    1024                 :             :          of the specified bit after the atomic operation (makes only sense
    1025                 :             :          for xor, otherwise the bit content is compile time known),
    1026                 :             :          we need to invert the bit.  */
    1027                 :          55 :       tree mask_convert = mask;
    1028                 :          55 :       gimple_seq stmts = NULL;
    1029                 :          55 :       if (!use_bool)
    1030                 :          43 :         mask_convert = gimple_convert (&stmts, TREE_TYPE (lhs), mask);
    1031                 :          55 :       new_lhs = gimple_build (&stmts, BIT_XOR_EXPR, TREE_TYPE (lhs), new_lhs,
    1032                 :          12 :                               use_bool ? build_int_cst (TREE_TYPE (lhs), 1)
    1033                 :             :                                        : mask_convert);
    1034                 :          55 :       if (throws)
    1035                 :             :         {
    1036                 :           9 :           gsi_insert_seq_on_edge_immediate (e, stmts);
    1037                 :          18 :           gsi = gsi_for_stmt (gimple_seq_last (stmts));
    1038                 :             :         }
    1039                 :             :       else
    1040                 :          46 :         gsi_insert_seq_after (&gsi, stmts, GSI_NEW_STMT);
    1041                 :             :     }
    1042                 :         427 :   if (use_bool && has_debug_uses)
    1043                 :             :     {
    1044                 :           1 :       tree temp = NULL_TREE;
    1045                 :           1 :       if (!throws || after || single_pred_p (e->dest))
    1046                 :             :         {
    1047                 :           1 :           temp = build_debug_expr_decl (TREE_TYPE (lhs));
    1048                 :           1 :           tree t = build2 (LSHIFT_EXPR, TREE_TYPE (lhs), new_lhs, bit);
    1049                 :           1 :           g = gimple_build_debug_bind (temp, t, g);
    1050                 :           1 :           if (throws && !after)
    1051                 :             :             {
    1052                 :           0 :               gsi = gsi_after_labels (e->dest);
    1053                 :           0 :               gsi_insert_before (&gsi, g, GSI_SAME_STMT);
    1054                 :             :             }
    1055                 :             :           else
    1056                 :           1 :             gsi_insert_after (&gsi, g, GSI_NEW_STMT);
    1057                 :             :         }
    1058                 :           4 :       FOR_EACH_IMM_USE_STMT (g, iter, use_lhs)
    1059                 :           2 :         if (is_gimple_debug (g))
    1060                 :             :           {
    1061                 :           1 :             use_operand_p use_p;
    1062                 :           1 :             if (temp == NULL_TREE)
    1063                 :           0 :               gimple_debug_bind_reset_value (g);
    1064                 :             :             else
    1065                 :           3 :               FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
    1066                 :           1 :                 SET_USE (use_p, temp);
    1067                 :           1 :             update_stmt (g);
    1068                 :           1 :           }
    1069                 :             :     }
    1070                 :         427 :   SSA_NAME_OCCURS_IN_ABNORMAL_PHI (new_lhs)
    1071                 :         427 :     = SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_lhs);
    1072                 :         427 :   replace_uses_by (use_lhs, new_lhs);
    1073                 :         427 :   gsi = gsi_for_stmt (use_stmt);
    1074                 :         427 :   gsi_remove (&gsi, true);
    1075                 :         427 :   release_defs (use_stmt);
    1076                 :         427 :   gsi_remove (gsip, true);
    1077                 :         427 :   release_ssa_name (lhs);
    1078                 :         427 :   return true;
    1079                 :             : }
    1080                 :             : 
    1081                 :             : /* Optimize
    1082                 :             :      _4 = __atomic_add_fetch_* (ptr_6, arg_2, _3);
    1083                 :             :      _5 = _4 == 0;
    1084                 :             :    to
    1085                 :             :      _4 = .ATOMIC_ADD_FETCH_CMP_0 (EQ_EXPR, ptr_6, arg_2, _3);
    1086                 :             :      _5 = _4;
    1087                 :             :    Similarly for __sync_add_and_fetch_* (without the ", _3" part
    1088                 :             :    in there).  */
    1089                 :             : 
    1090                 :             : static bool
    1091                 :        8978 : optimize_atomic_op_fetch_cmp_0 (gimple_stmt_iterator *gsip,
    1092                 :             :                                 enum internal_fn fn, bool has_model_arg)
    1093                 :             : {
    1094                 :        8978 :   gimple *call = gsi_stmt (*gsip);
    1095                 :        8978 :   tree lhs = gimple_call_lhs (call);
    1096                 :        8978 :   use_operand_p use_p;
    1097                 :        8978 :   gimple *use_stmt;
    1098                 :             : 
    1099                 :        8978 :   if (!flag_inline_atomics
    1100                 :        8978 :       || !gimple_call_builtin_p (call, BUILT_IN_NORMAL)
    1101                 :        8978 :       || !lhs
    1102                 :        6445 :       || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (lhs)
    1103                 :        6445 :       || !single_imm_use (lhs, &use_p, &use_stmt)
    1104                 :       15241 :       || !gimple_vdef (call))
    1105                 :        2715 :     return false;
    1106                 :             : 
    1107                 :        6263 :   optab optab;
    1108                 :        6263 :   switch (fn)
    1109                 :             :     {
    1110                 :             :     case IFN_ATOMIC_ADD_FETCH_CMP_0:
    1111                 :             :       optab = atomic_add_fetch_cmp_0_optab;
    1112                 :             :       break;
    1113                 :             :     case IFN_ATOMIC_SUB_FETCH_CMP_0:
    1114                 :             :       optab = atomic_sub_fetch_cmp_0_optab;
    1115                 :             :       break;
    1116                 :             :     case IFN_ATOMIC_AND_FETCH_CMP_0:
    1117                 :             :       optab = atomic_and_fetch_cmp_0_optab;
    1118                 :             :       break;
    1119                 :             :     case IFN_ATOMIC_OR_FETCH_CMP_0:
    1120                 :             :       optab = atomic_or_fetch_cmp_0_optab;
    1121                 :             :       break;
    1122                 :             :     case IFN_ATOMIC_XOR_FETCH_CMP_0:
    1123                 :             :       optab = atomic_xor_fetch_cmp_0_optab;
    1124                 :             :       break;
    1125                 :             :     default:
    1126                 :             :       return false;
    1127                 :             :     }
    1128                 :             : 
    1129                 :        6263 :   if (optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)))
    1130                 :             :       == CODE_FOR_nothing)
    1131                 :             :     return false;
    1132                 :             : 
    1133                 :        6245 :   tree use_lhs = lhs;
    1134                 :        6245 :   if (gimple_assign_cast_p (use_stmt))
    1135                 :             :     {
    1136                 :         925 :       use_lhs = gimple_assign_lhs (use_stmt);
    1137                 :         925 :       if (!tree_nop_conversion_p (TREE_TYPE (use_lhs), TREE_TYPE (lhs))
    1138                 :         911 :           || (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs))
    1139                 :          95 :               && !POINTER_TYPE_P (TREE_TYPE (use_lhs)))
    1140                 :         911 :           || SSA_NAME_OCCURS_IN_ABNORMAL_PHI (use_lhs)
    1141                 :        1836 :           || !single_imm_use (use_lhs, &use_p, &use_stmt))
    1142                 :          83 :         return false;
    1143                 :             :     }
    1144                 :        6162 :   enum tree_code code = ERROR_MARK;
    1145                 :        6162 :   tree op0 = NULL_TREE, op1 = NULL_TREE;
    1146                 :        6162 :   if (is_gimple_assign (use_stmt))
    1147                 :        1253 :     switch (gimple_assign_rhs_code (use_stmt))
    1148                 :             :       {
    1149                 :           0 :       case COND_EXPR:
    1150                 :           0 :         op1 = gimple_assign_rhs1 (use_stmt);
    1151                 :           0 :         code = TREE_CODE (op1);
    1152                 :           0 :         if (TREE_CODE_CLASS (code) == tcc_comparison)
    1153                 :             :           {
    1154                 :           0 :             op0 = TREE_OPERAND (op1, 0);
    1155                 :           0 :             op1 = TREE_OPERAND (op1, 1);
    1156                 :             :           }
    1157                 :             :         break;
    1158                 :        1253 :       default:
    1159                 :        1253 :         code = gimple_assign_rhs_code (use_stmt);
    1160                 :        1253 :         if (TREE_CODE_CLASS (code) == tcc_comparison)
    1161                 :             :           {
    1162                 :         842 :             op0 = gimple_assign_rhs1 (use_stmt);
    1163                 :         842 :             op1 = gimple_assign_rhs2 (use_stmt);
    1164                 :             :           }
    1165                 :             :         break;
    1166                 :             :       }
    1167                 :        4909 :   else if (gimple_code (use_stmt) == GIMPLE_COND)
    1168                 :             :     {
    1169                 :        4394 :       code = gimple_cond_code (use_stmt);
    1170                 :        4394 :       op0 = gimple_cond_lhs (use_stmt);
    1171                 :        4394 :       op1 = gimple_cond_rhs (use_stmt);
    1172                 :             :     }
    1173                 :             : 
    1174                 :        5647 :   switch (code)
    1175                 :             :     {
    1176                 :         243 :     case LT_EXPR:
    1177                 :         243 :     case LE_EXPR:
    1178                 :         243 :     case GT_EXPR:
    1179                 :         243 :     case GE_EXPR:
    1180                 :         486 :       if (!INTEGRAL_TYPE_P (TREE_TYPE (use_lhs))
    1181                 :         243 :           || TREE_CODE (TREE_TYPE (use_lhs)) == BOOLEAN_TYPE
    1182                 :         486 :           || TYPE_UNSIGNED (TREE_TYPE (use_lhs)))
    1183                 :             :         return false;
    1184                 :             :       /* FALLTHRU */
    1185                 :        5236 :     case EQ_EXPR:
    1186                 :        5236 :     case NE_EXPR:
    1187                 :        5236 :       if (op0 == use_lhs && integer_zerop (op1))
    1188                 :             :         break;
    1189                 :             :       return false;
    1190                 :             :     default:
    1191                 :             :       return false;
    1192                 :             :     }
    1193                 :             : 
    1194                 :        2306 :   int encoded;
    1195                 :        2306 :   switch (code)
    1196                 :             :     {
    1197                 :             :     /* Use special encoding of the operation.  We want to also
    1198                 :             :        encode the mode in the first argument and for neither EQ_EXPR
    1199                 :             :        etc. nor EQ etc. we can rely it will fit into QImode.  */
    1200                 :             :     case EQ_EXPR: encoded = ATOMIC_OP_FETCH_CMP_0_EQ; break;
    1201                 :         877 :     case NE_EXPR: encoded = ATOMIC_OP_FETCH_CMP_0_NE; break;
    1202                 :         106 :     case LT_EXPR: encoded = ATOMIC_OP_FETCH_CMP_0_LT; break;
    1203                 :          40 :     case LE_EXPR: encoded = ATOMIC_OP_FETCH_CMP_0_LE; break;
    1204                 :          40 :     case GT_EXPR: encoded = ATOMIC_OP_FETCH_CMP_0_GT; break;
    1205                 :          48 :     case GE_EXPR: encoded = ATOMIC_OP_FETCH_CMP_0_GE; break;
    1206                 :           0 :     default: gcc_unreachable ();
    1207                 :             :     }
    1208                 :             : 
    1209                 :        2306 :   tree new_lhs = make_ssa_name (boolean_type_node);
    1210                 :        2306 :   gimple *g;
    1211                 :        2306 :   tree flag = build_int_cst (TREE_TYPE (lhs), encoded);
    1212                 :        2306 :   if (has_model_arg)
    1213                 :        1898 :     g = gimple_build_call_internal (fn, 5, flag,
    1214                 :             :                                     gimple_call_arg (call, 0),
    1215                 :             :                                     gimple_call_arg (call, 1),
    1216                 :             :                                     gimple_call_arg (call, 2),
    1217                 :             :                                     gimple_call_fn (call));
    1218                 :             :   else
    1219                 :         408 :     g = gimple_build_call_internal (fn, 4, flag,
    1220                 :             :                                     gimple_call_arg (call, 0),
    1221                 :             :                                     gimple_call_arg (call, 1),
    1222                 :             :                                     gimple_call_fn (call));
    1223                 :        2306 :   gimple_call_set_lhs (g, new_lhs);
    1224                 :        2306 :   gimple_set_location (g, gimple_location (call));
    1225                 :        2306 :   gimple_move_vops (g, call);
    1226                 :        2306 :   bool throws = stmt_can_throw_internal (cfun, call);
    1227                 :        2306 :   gimple_call_set_nothrow (as_a <gcall *> (g),
    1228                 :        2306 :                            gimple_call_nothrow_p (as_a <gcall *> (call)));
    1229                 :        2306 :   gimple_stmt_iterator gsi = *gsip;
    1230                 :        2306 :   gsi_insert_after (&gsi, g, GSI_SAME_STMT);
    1231                 :        2306 :   if (throws)
    1232                 :           0 :     maybe_clean_or_replace_eh_stmt (call, g);
    1233                 :        2306 :   if (is_gimple_assign (use_stmt))
    1234                 :         816 :     switch (gimple_assign_rhs_code (use_stmt))
    1235                 :             :       {
    1236                 :           0 :       case COND_EXPR:
    1237                 :           0 :         gimple_assign_set_rhs1 (use_stmt, new_lhs);
    1238                 :           0 :         break;
    1239                 :         816 :       default:
    1240                 :         816 :         gsi = gsi_for_stmt (use_stmt);
    1241                 :         816 :         if (tree ulhs = gimple_assign_lhs (use_stmt))
    1242                 :         816 :           if (useless_type_conversion_p (TREE_TYPE (ulhs),
    1243                 :             :                                          boolean_type_node))
    1244                 :             :             {
    1245                 :         816 :               gimple_assign_set_rhs_with_ops (&gsi, SSA_NAME, new_lhs);
    1246                 :         816 :               break;
    1247                 :             :             }
    1248                 :           0 :         gimple_assign_set_rhs_with_ops (&gsi, NOP_EXPR, new_lhs);
    1249                 :           0 :         break;
    1250                 :             :       }
    1251                 :        1490 :   else if (gimple_code (use_stmt) == GIMPLE_COND)
    1252                 :             :     {
    1253                 :        1490 :       gcond *use_cond = as_a <gcond *> (use_stmt);
    1254                 :        1490 :       gimple_cond_set_code (use_cond, NE_EXPR);
    1255                 :        1490 :       gimple_cond_set_lhs (use_cond, new_lhs);
    1256                 :        1490 :       gimple_cond_set_rhs (use_cond, boolean_false_node);
    1257                 :             :     }
    1258                 :             : 
    1259                 :        2306 :   update_stmt (use_stmt);
    1260                 :        2306 :   if (use_lhs != lhs)
    1261                 :             :     {
    1262                 :         234 :       gsi = gsi_for_stmt (SSA_NAME_DEF_STMT (use_lhs));
    1263                 :         234 :       gsi_remove (&gsi, true);
    1264                 :         234 :       release_ssa_name (use_lhs);
    1265                 :             :     }
    1266                 :        2306 :   gsi_remove (gsip, true);
    1267                 :        2306 :   release_ssa_name (lhs);
    1268                 :        2306 :   return true;
    1269                 :             : }
    1270                 :             : 
    1271                 :             : /* Process builtin CALL located at GSI.
    1272                 :             :    Currently it is only fgr atomic functions optimizations from above. */
    1273                 :             : static void
    1274                 :     6903896 : gimple_isel_builtin_call (gcall *call, gimple_stmt_iterator *gsi)
    1275                 :             : {
    1276                 :             :   /* Don't handle these in non optimization mode or optimize debug mode.  */
    1277                 :     6903896 :   if (!optimize || optimize_debug)
    1278                 :             :     return;
    1279                 :             : 
    1280                 :     5387434 :   if (!gimple_call_builtin_p (call, BUILT_IN_NORMAL))
    1281                 :             :     return;
    1282                 :             : 
    1283                 :     1355190 :   tree callee = gimple_call_fndecl (call);
    1284                 :             :   
    1285                 :     1355190 :   switch (DECL_FUNCTION_CODE (callee))
    1286                 :             :     {
    1287                 :             : #define CASE_ATOMIC(NAME)                       \
    1288                 :             :       case BUILT_IN_##NAME##_1: \
    1289                 :             :       case BUILT_IN_##NAME##_2: \
    1290                 :             :       case BUILT_IN_##NAME##_4: \
    1291                 :             :       case BUILT_IN_##NAME##_8: \
    1292                 :             :       case BUILT_IN_##NAME##_16
    1293                 :             : #define CASE_ATOMIC_CMP0(ATOMIC, SYNC)                                  \
    1294                 :             :       CASE_ATOMIC(ATOMIC_##ATOMIC):                                     \
    1295                 :             :         optimize_atomic_op_fetch_cmp_0 (gsi,                            \
    1296                 :             :                                         IFN_ATOMIC_##ATOMIC##_CMP_0,    \
    1297                 :             :                                         true);                          \
    1298                 :             :         break;                                                          \
    1299                 :             :       CASE_ATOMIC(SYNC_##SYNC):                                         \
    1300                 :             :         optimize_atomic_op_fetch_cmp_0 (gsi,                            \
    1301                 :             :                                         IFN_ATOMIC_##ATOMIC##_CMP_0,    \
    1302                 :             :                                         false);                         \
    1303                 :             :       break;
    1304                 :             : 
    1305                 :             : 
    1306                 :        4150 :       CASE_ATOMIC_CMP0(ADD_FETCH, ADD_AND_FETCH)
    1307                 :        2579 :       CASE_ATOMIC_CMP0(SUB_FETCH, SUB_AND_FETCH)
    1308                 :         769 :       CASE_ATOMIC_CMP0(AND_FETCH, AND_AND_FETCH)
    1309                 :         766 :       CASE_ATOMIC_CMP0(OR_FETCH, OR_AND_FETCH)
    1310                 :             : #define CASE_ATOMIC_BIT_TEST_AND(ATOMIC, SYNC, FN, AFTER)               \
    1311                 :             :       CASE_ATOMIC(ATOMIC_##ATOMIC):                                     \
    1312                 :             :         optimize_atomic_bit_test_and (gsi,                              \
    1313                 :             :                                       IFN_ATOMIC_BIT_TEST_AND_##FN,     \
    1314                 :             :                                       true, AFTER);                     \
    1315                 :             :         break;                                                          \
    1316                 :             :       CASE_ATOMIC(SYNC_##SYNC):                                         \
    1317                 :             :         optimize_atomic_bit_test_and (gsi,                              \
    1318                 :             :                                       IFN_ATOMIC_BIT_TEST_AND_##FN,     \
    1319                 :             :                                       false, AFTER);                    \
    1320                 :             :         break;
    1321                 :        1429 :       CASE_ATOMIC_BIT_TEST_AND(FETCH_OR,  FETCH_AND_OR,  SET, false)
    1322                 :        1278 :       CASE_ATOMIC_BIT_TEST_AND(FETCH_XOR, FETCH_AND_XOR, COMPLEMENT, false)
    1323                 :        1137 :       CASE_ATOMIC_BIT_TEST_AND(FETCH_AND, FETCH_AND_AND, RESET, false)
    1324                 :             : 
    1325                 :         569 :       CASE_ATOMIC(ATOMIC_XOR_FETCH):
    1326                 :         569 :         if (optimize_atomic_bit_test_and
    1327                 :         569 :              (gsi, IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT, true, true))
    1328                 :             :           break;
    1329                 :         531 :         optimize_atomic_op_fetch_cmp_0 (gsi,
    1330                 :             :                                         IFN_ATOMIC_XOR_FETCH_CMP_0,
    1331                 :             :                                         true);
    1332                 :         531 :         break;
    1333                 :         200 :       CASE_ATOMIC(SYNC_XOR_AND_FETCH):
    1334                 :         200 :         if (optimize_atomic_bit_test_and
    1335                 :         200 :               (gsi, IFN_ATOMIC_BIT_TEST_AND_COMPLEMENT, false, true))
    1336                 :             :           break;
    1337                 :         183 :         optimize_atomic_op_fetch_cmp_0 (gsi,
    1338                 :             :                                         IFN_ATOMIC_XOR_FETCH_CMP_0,
    1339                 :             :                                         false);
    1340                 :         183 :         break;
    1341                 :             : 
    1342                 :          55 :       default:;
    1343                 :             :     }
    1344                 :             : }
    1345                 :             : 
    1346                 :             : /* Iterate all gimple statements and perform pre RTL expansion
    1347                 :             :    GIMPLE massaging to improve instruction selection.  */
    1348                 :             : 
    1349                 :             : unsigned int
    1350                 :     1472883 : pass_gimple_isel::execute (struct function *fun)
    1351                 :             : {
    1352                 :     1472883 :   gimple_stmt_iterator gsi;
    1353                 :     1472883 :   basic_block bb;
    1354                 :     1472883 :   bool cfg_changed = false;
    1355                 :             : 
    1356                 :    17170772 :   FOR_EACH_BB_FN (bb, fun)
    1357                 :             :     {
    1358                 :   128202511 :       for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
    1359                 :             :         {
    1360                 :             :           /* Give the target first try at replacing the instruction.  */
    1361                 :    96806733 :           cfg_changed |= targetm.instruction_selection (fun, &gsi);
    1362                 :             : 
    1363                 :             :           /* Pre-expand VEC_COND_EXPRs to .VCOND* internal function
    1364                 :             :              calls mapping to supported optabs.  */
    1365                 :    96806733 :           gimple *g = gimple_expand_vec_cond_expr (&gsi);
    1366                 :    96806733 :           if (g != NULL)
    1367                 :             :             {
    1368                 :       19104 :               tree lhs = gimple_assign_lhs (gsi_stmt (gsi));
    1369                 :       19104 :               gimple_set_lhs (g, lhs);
    1370                 :       19104 :               gsi_replace (&gsi, g, false);
    1371                 :             :             }
    1372                 :             : 
    1373                 :             :           /* Recognize .VEC_SET and .VEC_EXTRACT patterns.  */
    1374                 :    96806733 :           cfg_changed |= gimple_expand_vec_set_extract_expr (fun, &gsi);
    1375                 :    96806733 :           if (gsi_end_p (gsi))
    1376                 :             :             break;
    1377                 :             : 
    1378                 :    96806733 :           if (gcall *call = dyn_cast <gcall*>(*gsi))
    1379                 :             :             {
    1380                 :     6903896 :               gimple_isel_builtin_call (call, &gsi);
    1381                 :     6903896 :               continue;
    1382                 :             :             }
    1383                 :    89902837 :           gassign *stmt = dyn_cast <gassign *> (*gsi);
    1384                 :    89902837 :           if (!stmt)
    1385                 :    57861113 :             continue;
    1386                 :             : 
    1387                 :    32041724 :           tree_code code = gimple_assign_rhs_code (stmt);
    1388                 :    32041724 :           if (TREE_CODE_CLASS (code) == tcc_comparison)
    1389                 :      557250 :             maybe_duplicate_comparison (stmt, bb);
    1390                 :             :         }
    1391                 :             :     }
    1392                 :             : 
    1393                 :     1472883 :   return cfg_changed ? TODO_cleanup_cfg : 0;
    1394                 :             : }
    1395                 :             : 
    1396                 :             : } // anon namespace
    1397                 :             : 
    1398                 :             : gimple_opt_pass *
    1399                 :      289302 : make_pass_gimple_isel (gcc::context *ctxt)
    1400                 :             : {
    1401                 :      289302 :   return new pass_gimple_isel (ctxt);
    1402                 :             : }
    1403                 :             : 
        

Generated by: LCOV version 2.1-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.