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

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.